From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: "Toru TSUNEYOSHI" Newsgroups: gmane.emacs.devel Subject: Re: patch about moving file (or directory) to the Recycle Bin on Windows NT series Date: Sat, 26 Apr 2008 05:18:40 +0900 Message-ID: References: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_000F_01C8A75C.FCD95330" X-Trace: ger.gmane.org 1209184313 16083 80.91.229.12 (26 Apr 2008 04:31:53 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sat, 26 Apr 2008 04:31:53 +0000 (UTC) Cc: Stefan Monnier To: Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sat Apr 26 06:32:26 2008 connect(): Connection refused 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 1Jpc5H-0008GN-0z for ged-emacs-devel@m.gmane.org; Sat, 26 Apr 2008 06:32:23 +0200 Original-Received: from localhost ([127.0.0.1]:39528 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Jpc4a-0006mr-Q6 for ged-emacs-devel@m.gmane.org; Sat, 26 Apr 2008 00:31:40 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1JpUNd-0007ja-Vd for emacs-devel@gnu.org; Fri, 25 Apr 2008 16:18:50 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1JpUNb-0007jO-IK for emacs-devel@gnu.org; Fri, 25 Apr 2008 16:18:48 -0400 Original-Received: from [199.232.76.173] (port=42722 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JpUNb-0007jL-C9 for emacs-devel@gnu.org; Fri, 25 Apr 2008 16:18:47 -0400 Original-Received: from bay0-omc1-s22.bay0.hotmail.com ([65.54.246.94]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1JpUNa-0008Gl-S2 for emacs-devel@gnu.org; Fri, 25 Apr 2008 16:18:47 -0400 Original-Received: from hotmail.com ([207.46.10.16]) by bay0-omc1-s22.bay0.hotmail.com with Microsoft SMTPSVC(6.0.3790.3959); Fri, 25 Apr 2008 13:18:45 -0700 Original-Received: from mail pickup service by hotmail.com with Microsoft SMTPSVC; Fri, 25 Apr 2008 13:18:45 -0700 Original-Received: from 124.155.30.210 by BAY121-DAV6.phx.gbl with DAV; Fri, 25 Apr 2008 20:18:41 +0000 X-Originating-IP: [124.155.30.210] X-Originating-Email: [t_tuneyosi@hotmail.com] X-Sender: t_tuneyosi@hotmail.com X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2800.1914 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1914 X-OriginalArrivalTime: 25 Apr 2008 20:18:45.0374 (UTC) FILETIME=[901691E0:01C8A711] X-detected-kernel: by monty-python.gnu.org: Windows 2000 SP4, XP SP1+ X-Mailman-Approved-At: Sat, 26 Apr 2008 00:30:27 -0400 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:95966 Archived-At: This is a multi-part message in MIME format. ------=_NextPart_000_000F_01C8A75C.FCD95330 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit 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. ----- Original Message ----- From: "Stefan Monnier" To: "Toru TSUNEYOSHI" Cc: Sent: Thursday, April 24, 2008 12:35 AM Subject: Re: patch about moving file (or directory) to the Recycle Bin on Windows NT series > > I made a revised edition (including w32.h). > > I suggest we use a slightly different interface: > 1 - Implement a new Elisp function `move-file-to-trash'. > 2 - Add a config variable `delete-by-moving-to-trash' (default to nil). > > The implementation of delete-by-moving-to-trash will at first be naive: > if set, delete-file delegates the job to move-file-to-trash. > > > Stefan > > > PS: We will probably want to refine this implementation at some point so > that only some uses of delete-file are redirected to move-file-to-trash, > but let's start with that. ------=_NextPart_000_000F_01C8A75C.FCD95330 Content-Type: application/octet-stream; name="move-file-to-trash.el" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="move-file-to-trash.el" ;; 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))))) ------=_NextPart_000_000F_01C8A75C.FCD95330 Content-Type: application/octet-stream; name="patch__enable_delete_to_trash.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="patch__enable_delete_to_trash.diff" --- src/emacs.c.original 2008-01-10 21:16:14.000000000 +0900=0A= +++ src/emacs.c 2008-04-26 00:44:31.382475200 +0900=0A= @@ -1588,6 +1588,7 @@=0A= syms_of_vmsproc ();=0A= #endif /* VMS */=0A= #ifdef WINDOWSNT=0A= + syms_of_w32 ();=0A= syms_of_ntproc ();=0A= #endif /* WINDOWSNT */=0A= syms_of_window ();=0A= --- src/fileio.c.original 2008-03-11 10:56:52.000000000 +0900=0A= +++ src/fileio.c 2008-04-25 22:32:53.391973600 +0900=0A= @@ -231,6 +231,13 @@=0A= int write_region_inhibit_fsync;=0A= #endif=0A= =0A= +/* Nonzero means call move-file-to-trash in Fdelete_file or=0A= + Fdelete_directory. */=0A= +int delete_by_moving_to_trash;=0A= +=0A= +/* Lisp functions for move file to trash */=0A= +Lisp_Object Qmove_file_to_trash;=0A= +=0A= extern Lisp_Object Vuser_login_name;=0A= =0A= #ifdef WINDOWSNT=0A= @@ -2669,6 +2676,9 @@=0A= if (!NILP (handler))=0A= return call2 (handler, Qdelete_directory, directory);=0A= =0A= + if (delete_by_moving_to_trash)=0A= + return call1 (Qmove_file_to_trash, directory);=0A= +=0A= encoded_dir =3D ENCODE_FILE (directory);=0A= =0A= dir =3D SDATA (encoded_dir);=0A= @@ -2702,6 +2712,9 @@=0A= if (!NILP (handler))=0A= return call2 (handler, Qdelete_file, filename);=0A= =0A= + if (delete_by_moving_to_trash)=0A= + return call1 (Qmove_file_to_trash, filename);=0A= +=0A= encoded_file =3D ENCODE_FILE (filename);=0A= =0A= if (0 > unlink (SDATA (encoded_file)))=0A= @@ -6757,6 +6770,13 @@=0A= write_region_inhibit_fsync =3D 0;=0A= #endif=0A= =0A= + DEFVAR_BOOL ("delete-by-moving-to-trash", &delete_by_moving_to_trash,=0A= + doc: /* Non-nil means redirect to `move-file-to-trash'=0A= +by `delete-file' or `delete-directory'. */);=0A= + delete_by_moving_to_trash =3D 0;=0A= + Qmove_file_to_trash =3D intern ("move-file-to-trash");=0A= + staticpro (&Qmove_file_to_trash);=0A= +=0A= defsubr (&Sfind_file_name_handler);=0A= defsubr (&Sfile_name_directory);=0A= defsubr (&Sfile_name_nondirectory);=0A= --- src/lisp.h.original 2008-01-10 21:16:15.000000000 +0900=0A= +++ src/lisp.h 2008-04-25 23:50:59.844510400 +0900=0A= @@ -2898,6 +2898,8 @@=0A= extern void init_fileio_once P_ ((void));=0A= extern Lisp_Object make_temp_name P_ ((Lisp_Object, int));=0A= EXFUN (Fmake_symbolic_link, 3);=0A= +extern Lisp_Object Qdelete_directory;=0A= +extern Lisp_Object Qdelete_file;=0A= =0A= /* Defined in abbrev.c */=0A= =0A= --- src/w32.c.original 2008-02-23 22:49:09.000000000 +0900=0A= +++ src/w32.c 2008-04-26 03:33:03.212572800 +0900=0A= @@ -75,6 +75,11 @@=0A= #include =0A= #include =0A= =0A= +#include =0A= +#ifndef FOF_NO_CONNECTED_ELEMENTS=0A= +#define FOF_NO_CONNECTED_ELEMENTS 0x2000 /* don't operate on connected = elements. */=0A= +#endif /* FOF_NO_CONNECTED_ELEMENTS */=0A= +=0A= #ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */=0A= #include =0A= #undef socket=0A= @@ -96,6 +101,8 @@=0A= #undef sendto=0A= #endif=0A= =0A= +#include "charset.h"=0A= +#include "coding.h"=0A= #include "w32.h"=0A= #include "ndir.h"=0A= #include "w32heap.h"=0A= @@ -104,6 +111,7 @@=0A= typedef HRESULT (WINAPI * ShGetFolderPath_fn)=0A= (IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *);=0A= =0A= +void syms_of_w32 ();=0A= void globals_of_w32 ();=0A= =0A= extern Lisp_Object Vw32_downcase_file_names;=0A= @@ -2256,6 +2264,64 @@=0A= return _unlink (path);=0A= }=0A= =0A= +/* deverted from delete-file in fileio.c */=0A= +DEFUN ("w32-move-file-to-trash", Fw32_move_file_to_trash,=0A= + Sw32_move_file_to_trash, 1, 1, "fMove file to trash: ",=0A= + doc: /* Move file (or direcotry) named FILENAME. */)=0A= + (filename)=0A= + Lisp_Object filename;=0A= +{=0A= + Lisp_Object handler;=0A= + Lisp_Object encoded_file;=0A= + Lisp_Object operation;=0A= +=0A= + operation =3D Qdelete_file;=0A= + if (!NILP (Ffile_directory_p (filename))=0A= + && NILP (Ffile_symlink_p (filename)))=0A= + operation =3D Qdelete_directory;=0A= + filename =3D Fexpand_file_name (filename, Qnil);=0A= +=0A= + handler =3D Ffind_file_name_handler (filename, operation);=0A= + if (!NILP (handler))=0A= + return call2 (handler, operation, filename);=0A= +=0A= + encoded_file =3D ENCODE_FILE (filename);=0A= +=0A= + {=0A= + const char * path;=0A= + SHFILEOPSTRUCT file_op;=0A= + /* `pFrom' member of struct SHFILEOPSTRUCT:=0A= + Each file name must be terminated by a single NULL=0A= + character. An additional NULL character must be appended to the=0A= + end of the final name to indicate the end of pFrom. */=0A= + char tmp_path[MAX_PATH + 1];=0A= +=0A= + path =3D map_w32_filename (SDATA (encoded_file), NULL);=0A= +=0A= + /* On Unix, unlink works without write permission. */=0A= + _chmod (path, 0666);=0A= +=0A= + memset (tmp_path, 0, sizeof (tmp_path));=0A= + strcpy (tmp_path, path);=0A= +=0A= + memset (&file_op, 0, sizeof (file_op));=0A= + file_op.hwnd =3D HWND_DESKTOP;=0A= + file_op.wFunc =3D FO_DELETE;=0A= + file_op.pFrom =3D tmp_path;=0A= + file_op.pTo =3D NULL;=0A= + file_op.fFlags =3D FOF_SILENT | FOF_NOCONFIRMATION | FOF_ALLOWUNDO=0A= + | FOF_NOERRORUI | FOF_NO_CONNECTED_ELEMENTS;=0A= + file_op.fAnyOperationsAborted =3D FALSE;=0A= + file_op.hNameMappings =3D NULL;=0A= + file_op.lpszProgressTitle =3D NULL;=0A= +=0A= + if (SHFileOperation (&file_op) !=3D 0)=0A= + report_file_error ("Removing old name", list1 (filename));=0A= + }=0A= +=0A= + return Qnil;=0A= +}=0A= +=0A= static FILETIME utc_base_ft;=0A= static long double utc_base;=0A= static int init =3D 0;=0A= @@ -4140,6 +4206,12 @@=0A= return FALSE;=0A= }=0A= =0A= +void=0A= +syms_of_w32 ()=0A= +{=0A= + defsubr (&Sw32_move_file_to_trash);=0A= +}=0A= +=0A= /*=0A= globals_of_w32 is used to initialize those global variables that=0A= must always be initialized on startup even when the global variable=0A= --- src/w32.h.original 2008-01-10 21:16:16.000000000 +0900=0A= +++ src/w32.h 2008-04-26 00:43:48.961476800 +0900=0A= @@ -129,6 +129,7 @@=0A= =0A= extern void init_ntproc (void);=0A= extern void term_ntproc (void);=0A= +extern void syms_of_w32 (void);=0A= extern void globals_of_w32 (void);=0A= extern void syms_of_w32term (void);=0A= extern void syms_of_w32fns (void);=0A= ------=_NextPart_000_000F_01C8A75C.FCD95330--