all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: "Toru TSUNEYOSHI" <t_tuneyosi@hotmail.com>
To: <emacs-devel@gnu.org>
Cc: Stefan Monnier <monnier@iro.umontreal.ca>
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	[thread overview]
Message-ID: <BAY121-DAV6B811B0FB13F0DCD79E09E2DD0@phx.gbl> (raw)
In-Reply-To: jwvskxc37yg.fsf-monnier+emacs@gnu.org

[-- Attachment #1: Type: text/plain, Size: 1227 bytes --]

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" <monnier@iro.umontreal.ca>
To: "Toru TSUNEYOSHI" <t_tuneyosi@hotmail.com>
Cc: <emacs-devel@gnu.org>
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.

[-- Attachment #2: move-file-to-trash.el --]
[-- Type: application/octet-stream, Size: 2134 bytes --]

;; 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)))))

[-- Attachment #3: patch__enable_delete_to_trash.diff --]
[-- Type: application/octet-stream, Size: 5755 bytes --]

--- src/emacs.c.original	2008-01-10 21:16:14.000000000 +0900
+++ src/emacs.c	2008-04-26 00:44:31.382475200 +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.original	2008-03-11 10:56:52.000000000 +0900
+++ src/fileio.c	2008-04-25 22:32:53.391973600 +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.original	2008-01-10 21:16:15.000000000 +0900
+++ src/lisp.h	2008-04-25 23:50:59.844510400 +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.original	2008-02-23 22:49:09.000000000 +0900
+++ src/w32.c	2008-04-26 03:33:03.212572800 +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,64 @@
   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 = 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 +4206,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.original	2008-01-10 21:16:16.000000000 +0900
+++ src/w32.h	2008-04-26 00:43:48.961476800 +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);

  reply	other threads:[~2008-04-25 20:18 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-04-21 21:32 patch about moving file (or directory) to the Recycle Bin on Windows NT series Toru TSUNEYOSHI
2008-04-22  9:02 ` Toru TSUNEYOSHI
2008-04-22 15:47   ` Stefan Monnier
2008-04-22 17:04     ` Eli Zaretskii
2008-04-22 18:24       ` Eli Zaretskii
2008-04-22 18:19 ` Eli Zaretskii
2008-04-22 20:58   ` Jason Rumney
2008-04-23  1:15     ` Stefan Monnier
2008-04-23  1:14   ` Stefan Monnier
2008-04-23  4:55     ` Eli Zaretskii
2008-04-23 16:45   ` Toru TSUNEYOSHI
2008-04-23 15:35 ` Stefan Monnier
2008-04-25 20:18   ` Toru TSUNEYOSHI [this message]
  -- strict thread matches above, loose matches on Subject: below --
2008-05-27 17:11 Toru TSUNEYOSHI
2008-05-27 18:39 ` Stefan Monnier
2008-04-25 21:10 Toru TSUNEYOSHI
2008-04-26  7:25 ` Eli Zaretskii
2008-04-30 15:00   ` Toru TSUNEYOSHI
2008-05-15 17:36     ` Stefan Monnier
2008-05-25  0:07   ` Toru TSUNEYOSHI
2008-05-25  1:24 ` Stefan Monnier
2008-05-25  9:59   ` Jason Rumney
2008-05-25 11:22     ` Stefan Monnier
2008-04-21 14:25 patch is received? Toru TSUNEYOSHI
2008-04-21 16:37 ` Lennart Borgman (gmail)
2008-04-21 17:07   ` patch about moving file (or directory) to the Recycle Bin on Windows NT series Toru TSUNEYOSHI

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=BAY121-DAV6B811B0FB13F0DCD79E09E2DD0@phx.gbl \
    --to=t_tuneyosi@hotmail.com \
    --cc=emacs-devel@gnu.org \
    --cc=monnier@iro.umontreal.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.