changeset 96489:b76b9628d74f

Changes from Toru Tsuneyoshi for using Trash can when deleting files. * files.el (backup-extract-version): Handle versioned directories. (trash-directory): New variable. (move-file-to-trash): New function. * cus-start.el (delete-by-moving-to-trash): Declare for custom. * lisp.h (Qdelete_file, Qdelete_directory): Declare extern. * fileio.c (delete_by_moving_to_trash, Qmove_file_to_trash): New vars. (syms_of_fileio): Initialize and export them. (Fdelete_directory, Fdelete_file): Optionally delete via trash. * w32fns.c (FOF_NO_CONNECTED_ELEMENTS): Define if not already. (Fsystem_move_file_to_trash): New function. (syms_of_w32fns): Export it to lisp.
author Jason Rumney <jasonr@gnu.org>
date Wed, 02 Jul 2008 13:19:07 +0000
parents a30459da1bd7
children 2bab01f9c7bb
files lisp/ChangeLog lisp/cus-start.el lisp/files.el src/ChangeLog src/fileio.c src/lisp.h src/w32fns.c
diffstat 7 files changed, 149 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Wed Jul 02 13:17:41 2008 +0000
+++ b/lisp/ChangeLog	Wed Jul 02 13:19:07 2008 +0000
@@ -1,7 +1,15 @@
+2008-07-02  Toru Tsuneyoshi  <t_tuneyosi@hotmail.com>
+
+	* files.el (backup-extract-version): Handle versioned directories.
+	(trash-directory): New variable.
+	(move-file-to-trash): New function.
+
+	* cus-start.el (delete-by-moving-to-trash): Declare for custom.
+
 2008-07-02  Magnus Henoch  <mange@freemail.hu>
 
-    	* vc-git.el (vc-git-annotate-command): Use proper option for
-    	specifying revision.
+	* vc-git.el (vc-git-annotate-command): Use proper option for
+	specifying revision.
 
 2008-07-02  Francesc Rocher  <rocher@member.fsf.org>
 
--- a/lisp/cus-start.el	Wed Jul 02 13:17:41 2008 +0000
+++ b/lisp/cus-start.el	Wed Jul 02 13:19:07 2008 +0000
@@ -164,6 +164,8 @@
 					    :value (nil)
 					    (symbol :format "%v"))
 				    (const :tag "always" t)))
+             ;; fileio.c
+             (delete-by-moving-to-trash auto-save boolean "23.1")
 	     ;; fns.c
 	     (use-dialog-box menu boolean "21.1")
 	     (use-file-dialog menu boolean "22.1")
--- a/lisp/files.el	Wed Jul 02 13:17:41 2008 +0000
+++ b/lisp/files.el	Wed Jul 02 13:19:07 2008 +0000
@@ -31,7 +31,6 @@
 
 (defvar font-lock-keywords)
 
-
 (defgroup backup nil
   "Backups of edited data files."
   :group 'files)
@@ -3693,7 +3692,7 @@
   "Given the name of a numeric backup file, FN, return the backup number.
 Uses the free variable `backup-extract-version-start', whose value should be
 the index in the name where the version number begins."
-  (if (and (string-match "[0-9]+~$" fn backup-extract-version-start)
+  (if (and (string-match "[0-9]+~/?$" fn backup-extract-version-start)
 	   (= (match-beginning 0) backup-extract-version-start))
       (string-to-number (substring fn backup-extract-version-start -1))
       0))
@@ -5783,6 +5782,48 @@
 	(file-modes-symbolic-to-number value modes)))))
 
 
+;; Trash can handling.
+(defcustom trash-directory "~/.Trash"
+  "Directory for `move-file-to-trash' to move files and directories to.
+This directory is only used when the function `system-move-file-to-trash' is
+not defined.  Relative paths are interpreted relative to `default-directory'.
+See also `delete-by-moving-to-trash'."
+  :type 'directory
+  :group 'auto-save
+  :version "23.1")
+
+(declare-function system-move-file-to-trash "w32fns.c" (filename))
+
+(defun move-file-to-trash (filename)
+  "Move file (or directory) name FILENAME to the trash.
+This function is called by `delete-file' and `delete-directory' when
+`delete-by-moving-to-trash' is non-nil.  On platforms that define
+`system-move-file-to-trash', that function is used to move FILENAME to the
+system trash, otherwise FILENAME is moved to `trash-directory'.
+Returns nil on success."
+  (interactive "fMove file to trash: ")
+  (cond
+   ((fboundp 'system-move-file-to-trash)
+    (system-move-file-to-trash filename))
+   (t
+    (let* ((trash-dir   (expand-file-name trash-directory))
+           (fn          (directory-file-name (expand-file-name filename)))
+           (fn-nondir   (file-name-nondirectory fn))
+           (new-fn      (expand-file-name fn-nondir trash-dir)))
+      (or (file-directory-p trash-dir)
+          (make-directory trash-dir t))
+      (and (file-exists-p new-fn)
+           ;; make new-fn unique.
+           ;; example: "~/.Trash/abc.txt" -> "~/.Trash/abc.txt.~1~"
+           (let ((version-control t))
+             (setq new-fn (car (find-backup-file-name new-fn)))))
+      ;; stop processing if fn is same or parent directory of trash-dir.
+      (and (string-match fn trash-dir)
+           (error "Filename `%s' is same or parent directory of trash-directory"
+                  filename))
+      (rename-file fn new-fn)))))
+
+
 (define-key ctl-x-map "\C-f" 'find-file)
 (define-key ctl-x-map "\C-r" 'find-file-read-only)
 (define-key ctl-x-map "\C-v" 'find-alternate-file)
--- a/src/ChangeLog	Wed Jul 02 13:17:41 2008 +0000
+++ b/src/ChangeLog	Wed Jul 02 13:19:07 2008 +0000
@@ -1,3 +1,15 @@
+2008-07-02  Toru Tsuneyoshi  <t_tuneyosi@hotmail.com>
+
+        * lisp.h (Qdelete_file, Qdelete_directory): Declare extern.
+
+        * fileio.c (delete_by_moving_to_trash, Qmove_file_to_trash): New vars.
+        (syms_of_fileio): Initialize and export them.
+        (Fdelete_directory, Fdelete_file): Optionally delete via trash.
+
+        * w32fns.c (FOF_NO_CONNECTED_ELEMENTS): Define if not already.
+        (Fsystem_move_file_to_trash): New function.
+        (syms_of_w32fns): Export it to lisp.
+
 2008-07-01  Jason Rumney  <jasonr@gnu.org>
 
         * w32font.c (w32font_text_extents): Don't count overhang as part
--- a/src/fileio.c	Wed Jul 02 13:17:41 2008 +0000
+++ b/src/fileio.c	Wed Jul 02 13:19:07 2008 +0000
@@ -213,6 +213,13 @@
 int write_region_inhibit_fsync;
 #endif
 
+/* Non-zero means call move-file-to-trash in Fdelete_file or
+   Fdelete_directory.  */
+int delete_by_moving_to_trash;
+
+/* Lisp function for moving files to trash.  */
+Lisp_Object Qmove_file_to_trash;
+
 extern Lisp_Object Vuser_login_name;
 
 #ifdef WINDOWSNT
@@ -2674,6 +2681,9 @@
   if (!NILP (handler))
     return call2 (handler, Qdelete_directory, directory);
 
+  if (delete_by_moving_to_trash)
+    return call1 (Qmove_file_to_trash, directory);
+
   encoded_dir = ENCODE_FILE (directory);
 
   dir = SDATA (encoded_dir);
@@ -2707,6 +2717,9 @@
   if (!NILP (handler))
     return call2 (handler, Qdelete_file, filename);
 
+  if (delete_by_moving_to_trash)
+    return call1 (Qmove_file_to_trash, filename);
+
   encoded_file = ENCODE_FILE (filename);
 
   if (0 > unlink (SDATA (encoded_file)))
@@ -6358,6 +6371,14 @@
   write_region_inhibit_fsync = 0;
 #endif
 
+  DEFVAR_BOOL ("delete-by-moving-to-trash", &delete_by_moving_to_trash,
+               doc: /* Specifies whether to use the system's trash can.
+When non-nil, the function `move-file-to-trash' will be used by
+`delete-file' and `delete-directory'.  */);
+  delete_by_moving_to_trash = 0;
+  Qmove_file_to_trash = intern ("move-file-to-trash");
+  staticpro (&Qmove_file_to_trash);
+
   defsubr (&Sfind_file_name_handler);
   defsubr (&Sfile_name_directory);
   defsubr (&Sfile_name_nondirectory);
--- a/src/lisp.h	Wed Jul 02 13:17:41 2008 +0000
+++ b/src/lisp.h	Wed Jul 02 13:19:07 2008 +0000
@@ -2935,6 +2935,8 @@
 extern void init_fileio_once P_ ((void));
 extern Lisp_Object make_temp_name P_ ((Lisp_Object, int));
 EXFUN (Fmake_symbolic_link, 3);
+extern Lisp_Object Qdelete_directory;
+extern Lisp_Object Qdelete_file;
 
 /* Defined in abbrev.c */
 
--- a/src/w32fns.c	Wed Jul 02 13:17:41 2008 +0000
+++ b/src/w32fns.c	Wed Jul 02 13:19:07 2008 +0000
@@ -63,6 +63,10 @@
 #include "font.h"
 #include "w32font.h"
 
+#ifndef FOF_NO_CONNECTED_ELEMENTS
+#define FOF_NO_CONNECTED_ELEMENTS 0x2000
+#endif
+
 void syms_of_w32fns ();
 void globals_of_w32fns ();
 
@@ -6208,6 +6212,60 @@
 }
 
 
+/* Moving files to the system recycle bin.
+   Used by `move-file-to-trash' instead of the default moving to ~/.Trash  */
+DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash,
+       Ssystem_move_file_to_trash, 1, 1, 0,
+       doc: /* Move file or directory named FILENAME to the recycle bin.  */)
+     (filename)
+     Lisp_Object filename;
+{
+  Lisp_Object handler;
+  Lisp_Object encoded_file;
+  Lisp_Object operation;
+
+  operation = Qdelete_file;
+  if (!NILP (Ffile_directory_p (filename))
+      && NILP (Ffile_symlink_p (filename)))
+    {
+      operation = Qdelete_directory;
+      filename = Fdirectory_file_name (filename);
+    }
+  filename = Fexpand_file_name (filename, Qnil);
+
+  handler = Ffind_file_name_handler (filename, operation);
+  if (!NILP (handler))
+    return call2 (handler, operation, filename);
+
+  encoded_file = ENCODE_FILE (filename);
+
+  {
+    const char * path;
+    SHFILEOPSTRUCT file_op;
+    char tmp_path[MAX_PATH + 1];
+
+    path = map_w32_filename (SDATA (encoded_file), NULL);
+
+    /* On Windows, write permission is required to delete/move files.  */
+    _chmod (path, 0666);
+
+    bzero (tmp_path, sizeof (tmp_path));
+    strcpy (tmp_path, path);
+
+    bzero (&file_op, sizeof (file_op));
+    file_op.hwnd = HWND_DESKTOP;
+    file_op.wFunc = FO_DELETE;
+    file_op.pFrom = tmp_path;
+    file_op.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_ALLOWUNDO
+      | FOF_NOERRORUI | FOF_NO_CONNECTED_ELEMENTS;
+    file_op.fAnyOperationsAborted = FALSE;
+
+    if (SHFileOperation (&file_op) != 0)
+      report_file_error ("Removing old name", list1 (filename));
+  }
+  return Qnil;
+}
+
 
 /***********************************************************************
                          w32 specialized functions
@@ -7241,6 +7299,7 @@
   staticpro (&last_show_tip_args);
 
   defsubr (&Sx_file_dialog);
+  defsubr (&Ssystem_move_file_to_trash);
 }