diff --git a/ChangeLog b/ChangeLog
index 2eefacfd6049021f12a1303e9d1081ddcbf36805..51d4cca9d92efe4153d7c3b10ca9a8faa901de4a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2005-06-11	Benedikt Meurer <benny@xfce.org>
+
+	* thunar-vfs/thunar-vfs-uri.{c,h}: Add functions to ease the handling
+	  of URI lists, specifically to automatically parse and generate
+	  string representations of URI lists that conform to the
+	  text/uri-list mime type.
+	* thunar/thunar-location-buttons.c
+	  (thunar_location_buttons_drag_data_get): Use new ThunarVfsURI list
+	  handling functions instead.
+	* thunar/thunar-favourites-model.c
+	  (thunar_favourites_model_file_destroy): Handle the case where a
+	  directory referenced by a favourite disappears from the backend media.
+	* thunar/thunar-favourites-model.c
+	  (thunar_favourites_model_file_changed): Remove a given favourite if
+	  the system notices that the favourite's file no longer refers to a
+	  directory.
+	* thunar/thunar-favourites-model.c(thunar_favourites_model_init): Do
+	  not re-add favourites initially, that do not refer to a directory.
+	* thunar/thunar-favourites-model.{c,h}: Add a new method
+	  thunar_favourites_model_add(), which is used by the
+	  ThunarFavouritesView to add new favourites to the list and
+	  automatically sync the changes with the Gtk+ bookmarks list.
+	* thunar/thunar-favourites-view.c: Handle "text/uri-list" drops,
+	  adding new favourites as appropriate. Add note, that the initial
+	  idea is based on the GtkFileChooser written by Red Hat for Gtk+.
+	* TODO: Remove the 'text/uri-list'-handling for ThunarFavouritesView.
+	  Add item concerning the Trash in the favourites list.
+
 2005-06-10	Benedikt Meurer <benny@xfce.org>
 
 	* thunar/thunar-favourites-model.{c,h},
diff --git a/TODO b/TODO
index 0e961404b24eab2b7eebe1cda081890eec5868cc..f7f767fc04a316ab6cd3a57537b3e0948b52bf89 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,12 @@
 Important for Thunar 1.0
 ========================
 
- - Handle text/uri-list drops on the ThunarFavouritesView.
+ - ThunarFavouritesModel should include the 'Trash' in the default system
+   favourites list, given the user the ability to atleast empty the trash
+   by right-clicking on the favourite and choosing 'Empty trash bin' from
+   the context menu. An optional, yet tricky feature, would be to allow
+   dropping files to the trash bin in the favourites pane (not for 1.0 I'd
+   say).
 
  - ThunarFavouritesModel should watch the .gtk-bookmarks file for changes and
    reload it on-demand (take care of not reloading if the change was caused by
diff --git a/thunar-vfs/thunar-vfs-uri.c b/thunar-vfs/thunar-vfs-uri.c
index f472b194e4d65be71e8e955071442af602ce1dc8..a8a6f0a7189979c9a39269b1ee65a802b11df848 100644
--- a/thunar-vfs/thunar-vfs-uri.c
+++ b/thunar-vfs/thunar-vfs-uri.c
@@ -105,12 +105,18 @@ thunar_vfs_uri_new (const gchar *identifier,
 {
   ThunarVfsURI *uri;
   const gchar  *p;
+  gchar        *path;
 
   g_return_val_if_fail (identifier != NULL, NULL);
 
+  /* try to parse the path */
+  path = g_filename_from_uri (identifier, NULL, error);
+  if (G_UNLIKELY (path == NULL))
+    return NULL;
+
   /* allocate the URI instance */
   uri = g_object_new (THUNAR_VFS_TYPE_URI, NULL);
-  uri->path = g_filename_from_uri (identifier, NULL, error);
+  uri->path = path;
 
   /* determine the basename of the path */
   for (p = uri->name = uri->path; *p != '\0'; ++p)
@@ -273,7 +279,8 @@ thunar_vfs_uri_get_path (ThunarVfsURI *uri)
  * Returns the #ThunarVfsURI object that refers to the parent 
  * folder of @uri or %NULL if @uri has no parent.
  *
- * Return value:
+ * Return value: the #ThunarVfsURI object referring to the parent folder
+ *               or %NULL.
  **/
 ThunarVfsURI*
 thunar_vfs_uri_parent (ThunarVfsURI *uri)
@@ -305,7 +312,7 @@ thunar_vfs_uri_parent (ThunarVfsURI *uri)
  * @uri   : an #ThunarVfsURI instance.
  * @name  : the relative name.
  *
- * Return value:
+ * Return value: 
  **/
 ThunarVfsURI*
 thunar_vfs_uri_relative (ThunarVfsURI *uri,
@@ -429,4 +436,155 @@ thunar_vfs_uri_equal (gconstpointer a,
 
 
 
+/**
+ * thunar_vfs_uri_list_from_string:
+ * @string : string representation of an URI list.
+ * @error  : return location for errors.
+ *
+ * Splits an URI list conforming to the text/uri-list
+ * mime type defined in RFC 2483 into individual URIs,
+ * discarding any comments and whitespace.
+ *
+ * If all URIs were successfully parsed into #ThunarVfsURI
+ * objects, the list of parsed URIs will be returned, and
+ * you'll need to call #thunar_vfs_uri_list_free() to
+ * release the list resources. Else if the parsing fails
+ * at some point, %NULL will be returned and @error will
+ * be set to describe the cause.
+ *
+ * Note, that if @string contains no URIs, this function
+ * will also return %NULL, but @error won't be set. So
+ * take care when checking for an error condition!
+ *
+ * Return value: the list of #ThunarVfsURI's or %NULL.
+ **/
+GList*
+thunar_vfs_uri_list_from_string (const gchar *string,
+                                 GError     **error)
+{
+  ThunarVfsURI *uri;
+  const gchar  *s;
+  const gchar  *t;
+  GList        *uri_list = NULL;
+  gchar        *identifier;
+
+  g_return_val_if_fail (string != NULL, NULL);
+
+  for (s = string; s != NULL; )
+    {
+      if (*s != '#')
+        {
+          while (g_ascii_isspace (*s))
+            ++s;
+
+          for (t = s; *t != '\0' && *t != '\n' && *t != '\r'; ++t)
+            ;
+
+          if (t > s)
+            {
+              for (t--; t > s && g_ascii_isspace (*t); t--)
+                ;
+
+              if (t > s)
+                {
+                  /* try to parse the URI */
+                  identifier = g_strndup (s, t - s + 1);
+                  uri = thunar_vfs_uri_new (identifier, error);
+                  g_free (identifier);
+
+                  /* check if we succeed */
+                  if (G_UNLIKELY (uri == NULL))
+                    {
+                      thunar_vfs_uri_list_free (uri_list);
+                      return NULL;
+                    }
+                  else
+                    {
+                      /* append the newly parsed uri */
+                      uri_list = g_list_append (uri_list, uri);
+                    }
+                }
+            }
+        }
+
+      for (; *s != '\0' && *s != '\n'; ++s)
+        ;
+
+      if (*s++ == '\0')
+        break;
+    }
+
+  return uri_list;
+}
+
+
+
+/**
+ * thunar_vfs_uri_list_to_string:
+ * @uri_list : a list of #ThunarVfsURI<!---->s.
+ *
+ * Free the returned value using #g_free() when you
+ * are done with it.
+ *
+ * Return value: the string representation of @uri_list conforming to the
+ *               text/uri-list mime type defined in RFC 2483.
+ **/
+gchar*
+thunar_vfs_uri_list_to_string (GList *uri_list)
+{
+  gchar *string_list;
+  gchar *uri_string;
+  gchar *new_list;
+  GList *lp;
+
+  string_list = g_strdup ("");
+
+  /* This way of building up the string representation is pretty
+   * slow and can lead to serious heap fragmentation if called
+   * too often. But this doesn't matter, as this function is not
+   * called very often (in fact it should only be used in Thunar
+   * when a file drag is started from within Thunar). If you can
+   * think of any easy way to avoid calling malloc that often,
+   * let me know (of course without depending too much on the
+   * exact internal representation and the type of URIs). Else
+   * don't waste any time or thought on this.
+   */
+  for (lp = uri_list; lp != NULL; lp = lp->next)
+    {
+      g_assert (THUNAR_VFS_IS_URI (lp->data));
+
+      uri_string = thunar_vfs_uri_to_string (THUNAR_VFS_URI (lp->data));
+      new_list = g_strconcat (string_list, uri_string, "\r\n", NULL);
+      g_free (string_list);
+      g_free (uri_string);
+      string_list = new_list;
+    }
+
+  return string_list;
+}
+
+
+
+/**
+ * thunar_vfs_uri_list_free:
+ * @uri_list : a list of #ThunarVfsURI<!---->s.
+ *
+ * Frees the #ThunarVfsURI<!---->s contained in @uri_list and
+ * the @uri_list itself.
+ **/
+void
+thunar_vfs_uri_list_free (GList *uri_list)
+{
+  GList *lp;
+
+  for (lp = uri_list; lp != NULL; lp = lp->next)
+    {
+      g_assert (THUNAR_VFS_IS_URI (lp->data));
+      g_object_unref (G_OBJECT (lp->data));
+    }
+
+  g_list_free (uri_list);
+}
+
+
 
diff --git a/thunar-vfs/thunar-vfs-uri.h b/thunar-vfs/thunar-vfs-uri.h
index 9e5337977248f812fa1580f79b2d52872304aeaf..031879f7a2069ab37bbc3067ed878afa61826565 100644
--- a/thunar-vfs/thunar-vfs-uri.h
+++ b/thunar-vfs/thunar-vfs-uri.h
@@ -59,6 +59,16 @@ guint          thunar_vfs_uri_hash              (gconstpointer uri);
 gboolean       thunar_vfs_uri_equal             (gconstpointer a,
                                                  gconstpointer b);
 
+GList         *thunar_vfs_uri_list_from_string  (const gchar  *string,
+                                                 GError      **error);
+gchar         *thunar_vfs_uri_list_to_string    (GList        *uri_list);
+void           thunar_vfs_uri_list_free         (GList        *uri_list);
+
+#define thunar_vfs_uri_list_append(uri_list, uri) \
+  g_list_append ((uri_list), g_object_ref (G_OBJECT ((uri))))
+#define thunar_vfs_uri_list_prepend(uri_list, uri) \
+  g_list_prepend ((uri_list), g_object_ref (G_OBJECT ((uri))))
+
 G_END_DECLS;
 
 #endif /* !__THUNAR_VFS_URI_H__ */
diff --git a/thunar/thunar-favourites-model.c b/thunar/thunar-favourites-model.c
index 01e8d7f7c0d9b6e475af9af00fde44b8e457b374..232c2979c9c84dec67f3fa41c937cde89751fd13 100644
--- a/thunar/thunar-favourites-model.c
+++ b/thunar/thunar-favourites-model.c
@@ -170,6 +170,13 @@ thunar_favourites_model_init (ThunarFavouritesModel *model)
           if (G_UNLIKELY (file == NULL))
             continue;
 
+          /* make sure the file refers to a directory */
+          if (G_UNLIKELY (!thunar_file_is_directory (file)))
+            {
+              g_object_unref (G_OBJECT (file));
+              continue;
+            }
+
           /* create the favourite entry */
           favourite = g_new0 (ThunarFavourite, 1);
           favourite->file = file;
@@ -669,6 +676,16 @@ thunar_favourites_model_file_changed (ThunarFile            *file,
 
   g_return_if_fail (THUNAR_IS_FILE (file));
   g_return_if_fail (THUNAR_IS_FAVOURITES_MODEL (model));
+ 
+  /* check if the file still refers to a directory, else we cannot keep
+   * it on the favourites list, and so we'll treat it like the file
+   * was destroyed (and thereby removed)
+   */
+  if (G_UNLIKELY (!thunar_file_is_directory (file)))
+    {
+      thunar_favourites_model_file_destroy (file, model);
+      return;
+    }
 
   for (favourite = model->favourites, n = 0; favourite != NULL; favourite = favourite->next, ++n)
     if (favourite->file == file)
@@ -688,10 +705,52 @@ static void
 thunar_favourites_model_file_destroy (ThunarFile            *file,
                                       ThunarFavouritesModel *model)
 {
+  ThunarFavourite *favourite;
+  GtkTreePath     *path;
+  gint             n;
+
   g_return_if_fail (THUNAR_IS_FILE (file));
   g_return_if_fail (THUNAR_IS_FAVOURITES_MODEL (model));
 
-  // TODO: Implement this function.
+  /* lookup the favourite matching the file */
+  for (favourite = model->favourites, n = 0; favourite != NULL; favourite = favourite->next, ++n)
+    if (favourite->file == file)
+      break;
+
+  g_assert (favourite != NULL);
+  g_assert (n < model->n_favourites);
+  g_assert (THUNAR_IS_FILE (favourite->file));
+
+  /* unlink the favourite from the model */
+  --model->n_favourites;
+  if (favourite == model->favourites)
+    {
+      favourite->next->prev = NULL;
+      model->favourites = favourite->next;
+    }
+  else
+    {
+      if (favourite->next != NULL)
+        favourite->next->prev = favourite->prev;
+      favourite->prev->next = favourite->next;
+    }
+
+  /* tell everybody that we have lost a favourite */
+  path = gtk_tree_path_new_from_indices (n, -1);
+  gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
+  gtk_tree_path_free (path);
+
+  /* disconnect us from the favourite's file */
+  g_signal_handlers_disconnect_matched (G_OBJECT (favourite->file),
+                                        G_SIGNAL_MATCH_DATA, 0,
+                                        0, NULL, NULL, model);
+  g_object_unref (G_OBJECT (favourite->file));
+
+  /* the favourites list was changed, so write the gtk bookmarks file */
+  thunar_favourites_model_save (model);
+
+  /* free the favourite data */
+  g_free (favourite);
 }
 
 
@@ -822,6 +881,95 @@ thunar_favourites_model_drop_possible (ThunarFavouritesModel *model,
 
 
 
+/**
+ * thunar_favourites_model_add:
+ * @model    : a #ThunarFavouritesModel.
+ * @dst_path : the destination path.
+ * @file     : the #ThunarFile that should be added to the favourites list.
+ *
+ * Adds the favourite @file to the @model at @dst_path, unless @file is
+ * already present in @model in which case no action is performed.
+ **/
+void
+thunar_favourites_model_add (ThunarFavouritesModel *model,
+                             GtkTreePath           *dst_path,
+                             ThunarFile            *file)
+{
+  ThunarFavourite *favourite;
+  ThunarFavourite *current;
+  GtkTreeIter      iter;
+  gint             index;
+
+  g_return_if_fail (THUNAR_IS_FAVOURITES_MODEL (model));
+  g_return_if_fail (gtk_tree_path_get_depth (dst_path) > 0);
+  g_return_if_fail (gtk_tree_path_get_indices (dst_path)[0] >= 0);
+  g_return_if_fail (gtk_tree_path_get_indices (dst_path)[0] <= model->n_favourites);
+  g_return_if_fail (THUNAR_IS_FILE (file));
+
+  /* verify that the file is not already in use as favourite */
+  for (favourite = model->favourites; favourite != NULL; favourite = favourite->next)
+    if (G_UNLIKELY (favourite->file == file))
+      return;
+
+  /* create the new favourite that will be inserted */
+  favourite = g_new0 (ThunarFavourite, 1);
+  favourite->file = file;
+  g_object_ref (G_OBJECT (file));
+
+  /* we want to stay informed about changes to the file */
+  g_signal_connect (G_OBJECT (file), "changed",
+                    G_CALLBACK (thunar_favourites_model_file_changed), model);
+  g_signal_connect (G_OBJECT (file), "destroy",
+                    G_CALLBACK (thunar_favourites_model_file_destroy), model);
+
+  /* check if this is the first favourite to insert (shouldn't happen normally) */
+  if (G_UNLIKELY (model->favourites == NULL))
+    model->favourites = favourite;
+  else
+    {
+      index = gtk_tree_path_get_indices (dst_path)[0];
+      if (index == 0)
+        {
+          /* the new favourite should be prepended to the existing list */
+          favourite->next = model->favourites;
+          model->favourites->prev = favourite;
+          model->favourites = favourite;
+        }
+      else if (index == model->n_favourites)
+        {
+          /* the new favourite should be appended to the existing list */
+          for (current = model->favourites; current->next != NULL; current = current->next)
+            ;
+
+          favourite->prev = current;
+          current->next = favourite;
+        }
+      else
+        {
+          /* inserting somewhere into the existing list */
+          for (current = model->favourites; index-- > 0; current = current->next)
+            ;
+
+          favourite->next = current;
+          favourite->prev = current->prev;
+          current->prev->next = favourite;
+          current->prev = favourite;
+        }
+    }
+
+  /* we've just inserted a new item */
+  ++model->n_favourites;
+
+  /* tell everybody that we have a new favourite */
+  gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, dst_path);
+  gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), dst_path, &iter);
+
+  /* the favourites list was changed, so write the gtk bookmarks file */
+  thunar_favourites_model_save (model);
+}
+
+
+
 /**
  * thunar_favourites_model_move:
  * @model    : a #ThunarFavouritesModel.
diff --git a/thunar/thunar-favourites-model.h b/thunar/thunar-favourites-model.h
index 285fd26c7d0fef2f579c69521a12337ac5177016..a56dc3130d58d183cb3cae59f9807005b05e27f8 100644
--- a/thunar/thunar-favourites-model.h
+++ b/thunar/thunar-favourites-model.h
@@ -61,6 +61,9 @@ ThunarFile            *thunar_favourites_model_file_for_iter  (ThunarFavouritesM
 gboolean               thunar_favourites_model_drop_possible  (ThunarFavouritesModel *model,
                                                                GtkTreePath           *path);
 
+void                   thunar_favourites_model_add            (ThunarFavouritesModel *model,
+                                                               GtkTreePath           *dst_path,
+                                                               ThunarFile            *file);
 void                   thunar_favourites_model_move           (ThunarFavouritesModel *model,
                                                                GtkTreePath           *src_path,
                                                                GtkTreePath           *dst_path);
diff --git a/thunar/thunar-favourites-view.c b/thunar/thunar-favourites-view.c
index d1e0991cc8b24ce2b42bd7237a6a3281782ef095..020bfc294f0a0231edbc3a1fa9aa267a22adfe29 100644
--- a/thunar/thunar-favourites-view.c
+++ b/thunar/thunar-favourites-view.c
@@ -15,6 +15,9 @@
  * You should have received a copy of the GNU General Public License along with
  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  * Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Inspired by the shortcuts list as found in the GtkFileChooser, which was
+ * developed for Gtk+ by Red Hat, Inc.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -67,6 +70,9 @@ static gboolean     thunar_favourites_view_drag_motion            (GtkWidget
 static GtkTreePath *thunar_favourites_view_compute_drop_position  (ThunarFavouritesView      *view,
                                                                    gint                       x,
                                                                    gint                       y);
+static void         thunar_favourites_view_drop_uri_list          (ThunarFavouritesView      *view,
+                                                                   const gchar               *uri_list,
+                                                                   GtkTreePath               *dst_path);
 #if GTK_CHECK_VERSION(2,6,0)
 static gboolean     thunar_favourites_view_separator_func         (GtkTreeModel              *model,
                                                                    GtkTreeIter               *iter,
@@ -238,7 +244,7 @@ thunar_favourites_view_drag_data_received (GtkWidget        *widget,
 
   if (selection_data->target == gdk_atom_intern ("text/uri-list", FALSE))
     {
-      g_error ("text/uri-list not handled yet");
+      thunar_favourites_view_drop_uri_list (view, selection_data->data, dst_path);
     }
   else if (selection_data->target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
     {
@@ -368,6 +374,71 @@ thunar_favourites_view_compute_drop_position (ThunarFavouritesView *view,
 
 
 
+static void
+thunar_favourites_view_drop_uri_list (ThunarFavouritesView *view,
+                                      const gchar          *uri_list,
+                                      GtkTreePath          *dst_path)
+{
+  GtkTreeModel *model;
+  ThunarFile   *file;
+  GtkWidget    *toplevel;
+  GtkWidget    *dialog;
+  GError       *error = NULL;
+  gchar        *uri_string;
+  GList        *uris;
+  GList        *lp;
+
+  uris = thunar_vfs_uri_list_from_string (uri_list, &error);
+  if (G_LIKELY (error == NULL))
+    {
+      /* process the URIs one-by-one and stop on error */
+      model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
+      for (lp = uris; lp != NULL; lp = lp->next)
+        {
+          file = thunar_file_get_for_uri (lp->data, &error);
+          if (G_UNLIKELY (file == NULL))
+            break;
+
+          /* make sure, that only directories gets added to the favourites list */
+          if (G_UNLIKELY (!thunar_file_is_directory (file)))
+            {
+              uri_string = thunar_vfs_uri_to_string (lp->data);
+              g_set_error (&error, G_FILE_ERROR, G_FILE_ERROR_NOTDIR,
+                           "The URI '%s' does not refer to a directory",
+                           uri_string);
+              g_object_unref (G_OBJECT (file));
+              g_free (uri_string);
+              break;
+            }
+
+          thunar_favourites_model_add (THUNAR_FAVOURITES_MODEL (model), dst_path, file);
+          g_object_unref (G_OBJECT (file));
+          gtk_tree_path_next (dst_path);
+        }
+
+      thunar_vfs_uri_list_free (uris);
+    }
+
+  if (G_UNLIKELY (error != NULL))
+    {
+      toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view));
+      dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW (toplevel),
+                                                   GTK_DIALOG_DESTROY_WITH_PARENT
+                                                   | GTK_DIALOG_MODAL,
+                                                   GTK_MESSAGE_ERROR,
+                                                   GTK_BUTTONS_OK,
+                                                   "<span weight=\"bold\" size="
+                                                   "\"larger\">%s</span>\n\n%s",
+                                                   _("Could not add favourite"),
+                                                   error->message);
+      gtk_dialog_run (GTK_DIALOG (dialog));
+      gtk_widget_destroy (dialog);
+      g_error_free (error);
+    }
+}
+
+
+
 #if GTK_CHECK_VERSION(2,6,0)
 static gboolean
 thunar_favourites_view_separator_func (GtkTreeModel *model,
diff --git a/thunar/thunar-location-buttons.c b/thunar/thunar-location-buttons.c
index df06f8660df2febcc58ac75ee570afa7730f4a6d..6fb84104561fe2b3b255ba483f23bc2683c4540f 100644
--- a/thunar/thunar-location-buttons.c
+++ b/thunar/thunar-location-buttons.c
@@ -1009,7 +1009,7 @@ thunar_location_buttons_drag_data_get (GtkWidget             *button,
 {
   ThunarVfsURI *uri;
   ThunarFile   *file;
-  gchar        *uri_list;
+  GList        *uri_list = NULL;
   gchar        *uri_string;
 
   g_return_if_fail (GTK_IS_WIDGET (button));
@@ -1019,17 +1019,17 @@ thunar_location_buttons_drag_data_get (GtkWidget             *button,
   file = g_object_get_qdata (G_OBJECT (button), thunar_file_quark);
   uri = thunar_file_get_uri (file);
 
-  /* transform the uri into an uri list (using DOS line endings!) */
-  uri_string = thunar_vfs_uri_to_string (uri);
-  uri_list = g_strconcat (uri_string, "\r\n", NULL);
+  /* transform the uri into an uri list string */
+  uri_list = thunar_vfs_uri_list_prepend (uri_list, uri);
+  uri_string = thunar_vfs_uri_list_to_string (uri_list);
+  thunar_vfs_uri_list_free (uri_list);
 
   /* set the uri list for the drag selection */
   gtk_selection_data_set (selection_data, selection_data->target,
-                          8, uri_list, strlen (uri_list));
+                          8, uri_string, strlen (uri_string));
 
   /* cleanup */
   g_free (uri_string);
-  g_free (uri_list);
 }