From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Stefan Monnier Newsgroups: gmane.emacs.devel 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 Message-ID: References: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1211678714 5663 80.91.229.12 (25 May 2008 01:25:14 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sun, 25 May 2008 01:25:14 +0000 (UTC) To: Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sun May 25 03:25:54 2008 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1K04zh-0007db-JL for ged-emacs-devel@m.gmane.org; Sun, 25 May 2008 03:25:54 +0200 Original-Received: from localhost ([127.0.0.1]:46296 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1K04yw-0006Ym-Lp for ged-emacs-devel@m.gmane.org; Sat, 24 May 2008 21:25:06 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1K04yq-0006Um-Jp for emacs-devel@gnu.org; Sat, 24 May 2008 21:25:00 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1K04yp-0006SW-IO for emacs-devel@gnu.org; Sat, 24 May 2008 21:25:00 -0400 Original-Received: from [199.232.76.173] (port=42198 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1K04yp-0006SB-Dg for emacs-devel@gnu.org; Sat, 24 May 2008 21:24:59 -0400 Original-Received: from 206-248-174-248.dsl.teksavvy.com ([206.248.174.248]:44943 helo=ceviche.home) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1K04yp-0005Yg-4r for emacs-devel@gnu.org; Sat, 24 May 2008 21:24:59 -0400 Original-Received: by ceviche.home (Postfix, from userid 20848) id B0C74B400C; Sat, 24 May 2008 21:24:52 -0400 (EDT) In-Reply-To: (Toru TSUNEYOSHI's message of "Sat, 26 Apr 2008 06:10:34 +0900") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) X-detected-kernel: by monty-python.gnu.org: Linux 2.6 (newer, 3) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:97679 Archived-At: Can someone take care of installing this, please? Stefan >>>>> "Toru" == Toru TSUNEYOSHI 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" > To: > Cc: "Stefan Monnier" > 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 > #include > +#include > +#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 > #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);