[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: patch about moving file (or directory) to the Recycle Bin on Windows
From: |
Stefan Monnier |
Subject: |
Re: patch about moving file (or directory) to the Recycle Bin on Windows NT series |
Date: |
Sat, 24 May 2008 21:24:52 -0400 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) |
Can someone take care of installing this, please?
Stefan
>>>>> "Toru" == Toru TSUNEYOSHI <address@hidden> writes:
> A bug was function w32-move-file-to-trash in w32.c
> example: ("~/test" is directory)
> (w32-move-file-to-trash "~/test")
> => ok
> (w32-move-file-to-trash "~/test/")
> => error
> So I fixed it.
> (w32-move-file-to-trash "~/test/")
> => ok
> Please use this patch not old one.
> ----- Original Message -----
> From: "Toru TSUNEYOSHI" <address@hidden>
> To: <address@hidden>
> Cc: "Stefan Monnier" <address@hidden>
> Sent: Saturday, April 26, 2008 5:18 AM
> Subject: Re: patch about moving file (or directory) to the Recycle Bin on
> Windows NT series
>> Now I made new patch for function move-file-to-trash (maybe as you
>> wrote).
>>
>> step to enable move-file-to-trash:
>>
>> cd src
>> patch -i patch__enable_delete_to_trash.diff
>> make all install
>>
>> Run emacs
>> (load-file "move-file-to-trash.el")
>> (setq delete-by-moving-to-trash t)
>>
>> I think it is useful. And I wish that someone else improve the code.
> ;; moved to C source code
> ;;
> ;; (defvar delete-by-moving-to-trash nil
> ;; "Non nil means redirect to `move-file-to-trash'
> ;; by `delete-file' or `delete-directory'")
> (or (functionp 'orig-backup-extract-version)
> (fset 'orig-backup-extract-version (symbol-function
> 'backup-extract-version)))
> ;; Note: The following function can deal with directory properly.
> (defun backup-extract-version (fn)
> "Given the name of a numeric backup file, 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)
> (= (match-beginning 0) backup-extract-version-start))
> (string-to-int (substring fn backup-extract-version-start -1))
> 0))
> (defvar trash-directory "~/.trash"
> "Trash directory to move file (or directory) by `move-file-to-trash',
> when system-specific move-file-to-trash doesn't exist.
> If set \".trash\", always move to the directory under default-directory.
> See also `delete-by-moving-to-trash'.")
> (defun move-file-to-trash (filename)
> "Move file (or directory) named FILENAME.
> Usually this function is called by `delete-file' or `delete-directory',
> so must return nil if succeed."
> (interactive "fMove file to trash: ")
> (cond
> ((eq system-type 'windows-nt)
> (w32-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))
> (when (file-exists-p new-fn)
> ;; change unique new-fn.
> ;; 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 (message "filename `%s' is same or parent directory of
> trash-directory."
> filename)))
> (rename-file fn new-fn)))))
> --- src/emacs.c.orig 2008-01-10 21:16:14.000000000 +0900
> +++ src/emacs.c 2008-04-26 00:44:31.000000000 +0900
> @@ -1588,6 +1588,7 @@
> syms_of_vmsproc ();
> #endif /* VMS */
> #ifdef WINDOWSNT
> + syms_of_w32 ();
> syms_of_ntproc ();
> #endif /* WINDOWSNT */
> syms_of_window ();
> --- src/fileio.c.orig 2008-03-11 10:56:52.000000000 +0900
> +++ src/fileio.c 2008-04-25 22:32:53.000000000 +0900
> @@ -231,6 +231,13 @@
> int write_region_inhibit_fsync;
> #endif
> +/* Nonzero means call move-file-to-trash in Fdelete_file or
> + Fdelete_directory. */
> +int delete_by_moving_to_trash;
> +
> +/* Lisp functions for move file to trash */
> +Lisp_Object Qmove_file_to_trash;
> +
> extern Lisp_Object Vuser_login_name;
> #ifdef WINDOWSNT
> @@ -2669,6 +2676,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);
> @@ -2702,6 +2712,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)))
> @@ -6757,6 +6770,13 @@
> write_region_inhibit_fsync = 0;
> #endif
> + DEFVAR_BOOL ("delete-by-moving-to-trash", &delete_by_moving_to_trash,
> + doc: /* Non-nil means redirect to `move-file-to-trash'
> +by `delete-file' or `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);
> --- src/lisp.h.orig 2008-01-10 21:16:15.000000000 +0900
> +++ src/lisp.h 2008-04-26 04:07:07.582232000 +0900
> @@ -2898,6 +2898,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 */
> --- src/w32.c.orig 2008-02-23 22:49:09.000000000 +0900
> +++ src/w32.c 2008-04-26 05:47:03.929566500 +0900
> @@ -75,6 +75,11 @@
> #include <windows.h>
> #include <shlobj.h>
> +#include <shellapi.h>
> +#ifndef FOF_NO_CONNECTED_ELEMENTS
> +#define FOF_NO_CONNECTED_ELEMENTS 0x2000 /* don't operate on connected
> elements. */
> +#endif /* FOF_NO_CONNECTED_ELEMENTS */
> +
> #ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
> #include <sys/socket.h>
> #undef socket
> @@ -96,6 +101,8 @@
> #undef sendto
> #endif
> +#include "charset.h"
> +#include "coding.h"
> #include "w32.h"
> #include "ndir.h"
> #include "w32heap.h"
> @@ -104,6 +111,7 @@
> typedef HRESULT (WINAPI * ShGetFolderPath_fn)
> (IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *);
> +void syms_of_w32 ();
> void globals_of_w32 ();
> extern Lisp_Object Vw32_downcase_file_names;
> @@ -2256,6 +2264,67 @@
> return _unlink (path);
> }
> +/* deverted from delete-file in fileio.c */
> +DEFUN ("w32-move-file-to-trash", Fw32_move_file_to_trash,
> + Sw32_move_file_to_trash, 1, 1, "fMove file to trash: ",
> + doc: /* Move file (or direcotry) named FILENAME. */)
> + (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, Qnil);
> + }
> + 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;
> + /* `pFrom' member of struct SHFILEOPSTRUCT:
> + Each file name must be terminated by a single NULL
> + character. An additional NULL character must be appended to the
> + end of the final name to indicate the end of pFrom. */
> + char tmp_path[MAX_PATH + 1];
> +
> + path = map_w32_filename (SDATA (encoded_file), NULL);
> +
> + /* On Unix, unlink works without write permission. */
> + _chmod (path, 0666);
> +
> + memset (tmp_path, 0, sizeof (tmp_path));
> + strcpy (tmp_path, path);
> +
> + memset (&file_op, 0, sizeof (file_op));
> + file_op.hwnd = HWND_DESKTOP;
> + file_op.wFunc = FO_DELETE;
> + file_op.pFrom = tmp_path;
> + file_op.pTo = NULL;
> + file_op.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_ALLOWUNDO
> + | FOF_NOERRORUI | FOF_NO_CONNECTED_ELEMENTS;
> + file_op.fAnyOperationsAborted = FALSE;
> + file_op.hNameMappings = NULL;
> + file_op.lpszProgressTitle = NULL;
> +
> + if (SHFileOperation (&file_op) != 0)
> + report_file_error ("Removing old name", list1 (filename));
> + }
> +
> + return Qnil;
> +}
> +
> static FILETIME utc_base_ft;
> static long double utc_base;
> static int init = 0;
> @@ -4140,6 +4209,12 @@
> return FALSE;
> }
> +void
> +syms_of_w32 ()
> +{
> + defsubr (&Sw32_move_file_to_trash);
> +}
> +
> /*
> globals_of_w32 is used to initialize those global variables that
> must always be initialized on startup even when the global variable
> --- src/w32.h.orig 2008-01-10 21:16:16.000000000 +0900
> +++ src/w32.h 2008-04-26 00:43:49.000000000 +0900
> @@ -129,6 +129,7 @@
> extern void init_ntproc (void);
> extern void term_ntproc (void);
> +extern void syms_of_w32 (void);
> extern void globals_of_w32 (void);
> extern void syms_of_w32term (void);
> extern void syms_of_w32fns (void);