unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Re: patch about moving file (or directory) to the Recycle Bin on Windows NT series
@ 2008-04-21 21:32 Toru TSUNEYOSHI
  2008-04-22  9:02 ` Toru TSUNEYOSHI
                   ` (2 more replies)
  0 siblings, 3 replies; 24+ messages in thread
From: Toru TSUNEYOSHI @ 2008-04-21 21:32 UTC (permalink / raw)
  To: emacs-devel

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

I made a revised edition (including w32.h).

[-- Attachment #2: w32.h_w32.c_emacs.c.diff --]
[-- Type: application/octet-stream, Size: 4326 bytes --]

--- w32.h.original	2008-01-10 21:16:16.000000000 +0900
+++ w32.h	2008-04-22 05:52:24.056379500 +0900
@@ -129,6 +129,9 @@
 
 extern void init_ntproc (void);
 extern void term_ntproc (void);
+#ifdef W32_SYS_UNLINK_USE_SHELLAPI
+extern void syms_of_w32 (void);
+#endif /* W32_SYS_UNLINK_USE_SHELLAPI */
 extern void globals_of_w32 (void);
 extern void syms_of_w32term (void);
 extern void syms_of_w32fns (void);
--- w32.c.original	2008-02-23 22:49:09.000000000 +0900
+++ w32.c	2008-04-22 05:51:43.056197700 +0900
@@ -75,6 +75,10 @@
 #include <windows.h>
 #include <shlobj.h>
 
+#ifdef W32_SYS_UNLINK_USE_SHELLAPI
+#include <shellapi.h>
+#endif /* W32_SYS_UNLINK_USE_SHELLAPI */
+
 #ifdef HAVE_SOCKETS	/* TCP connection support, if kernel can do it */
 #include <sys/socket.h>
 #undef socket
@@ -104,6 +108,9 @@
 typedef HRESULT (WINAPI * ShGetFolderPath_fn)
   (IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *);
 
+#ifdef W32_SYS_UNLINK_USE_SHELLAPI
+void syms_of_w32 ();
+#endif /* W32_SYS_UNLINK_USE_SHELLAPI */
 void globals_of_w32 ();
 
 extern Lisp_Object Vw32_downcase_file_names;
@@ -111,6 +118,10 @@
 extern Lisp_Object Vw32_get_true_file_attributes;
 extern int w32_num_mouse_buttons;
 
+#ifdef W32_SYS_UNLINK_USE_SHELLAPI
+int w32_sys_unlink_use_shellapi;
+#endif /* W32_SYS_UNLINK_USE_SHELLAPI */
+
 \f
 /*
   Initialization states
@@ -2240,6 +2251,71 @@
   return result;
 }
 
+#ifdef W32_SYS_UNLINK_USE_SHELLAPI
+
+int
+sys_rmdir (const char * path)
+{
+  if (w32_sys_unlink_use_shellapi)
+    return (sys_unlink ((const char *)path));
+  else
+    return _rmdir (map_w32_filename (path, NULL));
+}
+
+int
+sys_unlink (const char * path)
+{
+  if (w32_sys_unlink_use_shellapi)
+    {
+      /* 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. */
+      TCHAR tmp_path[MAX_PATH + 1 + 1];
+      SHFILEOPSTRUCT stFileOp;
+
+      path = map_w32_filename (path, NULL);
+
+      /* On Unix, unlink works without write permission. */
+      _chmod (path, 0666);
+
+#if 0
+      *(tmp_path + lstrlen(tmp_path) + 1) = '\0';
+#else
+      ZeroMemory(tmp_path, sizeof(tmp_path));
+#endif
+      lstrcpy(tmp_path, path);
+
+      ZeroMemory(&stFileOp, sizeof(SHFILEOPSTRUCT));
+      stFileOp.hwnd = HWND_DESKTOP;
+      stFileOp.wFunc = FO_DELETE;
+      stFileOp.pFrom = tmp_path;
+      stFileOp.pTo = NULL;
+      stFileOp.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_SILENT;
+      stFileOp.fAnyOperationsAborted = FALSE;
+      stFileOp.hNameMappings = NULL;
+      stFileOp.lpszProgressTitle = NULL;
+
+#if 0
+      SHFileOperation(&stFileOp);
+
+      return (stFileOp.fAnyOperationsAborted);
+#else
+      /* value returned by SHFileOperation() must match value returned by _unlink() */
+      return (SHFileOperation(&stFileOp) == 0 ? 0 : -1);
+#endif
+    }
+  else
+    {
+      path = map_w32_filename (path, NULL);
+
+      /* On Unix, unlink works without write permission. */
+      _chmod (path, 0666);
+      return _unlink (path);
+    }
+}
+
+#else /* W32_SYS_UNLINK_USE_SHELLAPI */
+
 int
 sys_rmdir (const char * path)
 {
@@ -2256,6 +2332,8 @@
   return _unlink (path);
 }
 
+#endif /* W32_SYS_UNLINK_USE_SHELLAPI */
+
 static FILETIME utc_base_ft;
 static long double utc_base;
 static int init = 0;
@@ -4160,6 +4238,18 @@
   SetConsoleCtrlHandler(shutdown_handler, TRUE);
 }
 
+#ifdef W32_SYS_UNLINK_USE_SHELLAPI
+
+void
+syms_of_w32 ()
+{
+  DEFVAR_BOOL ("w32-sys-unlink-use-shellapi", &w32_sys_unlink_use_shellapi,
+	       "Non-nil means using shellapi for sys_unlink(), sys_rmdir().");
+  w32_sys_unlink_use_shellapi = 1;
+}
+
+#endif /* W32_SYS_UNLINK_USE_SHELLAPI */
+
 /* end of w32.c */
 
 /* arch-tag: 90442dd3-37be-482b-b272-ac752e3049f1
--- emacs.c.original	2008-01-10 21:16:14.000000000 +0900
+++ emacs.c	2008-04-22 05:49:48.407912100 +0900
@@ -1588,6 +1588,9 @@
       syms_of_vmsproc ();
 #endif /* VMS */
 #ifdef WINDOWSNT
+#ifdef W32_SYS_UNLINK_USE_SHELLAPI
+      syms_of_w32 ();
+#endif /* W32_SYS_UNLINK_USE_SHELLAPI */
       syms_of_ntproc ();
 #endif /* WINDOWSNT */
       syms_of_window ();

^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: patch about moving file (or directory) to the Recycle Bin on Windows NT series
@ 2008-05-27 17:11 Toru TSUNEYOSHI
  2008-05-27 18:39 ` Stefan Monnier
  0 siblings, 1 reply; 24+ messages in thread
From: Toru TSUNEYOSHI @ 2008-05-27 17:11 UTC (permalink / raw)
  To: emacs-devel

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

Thanks for your helping, Jason and Stefan.
I fixed a patch according to it.
(I read archives on http://lists.gnu.org/archive/html/emacs-devel/.)

(I write again.)
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)

[-- Attachment #2: move-file-to-trash.el --]
[-- Type: application/octet-stream, Size: 2154 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
   ((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 (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: 5681 bytes --]

--- src/emacs.c.orig	2008-01-10 21:16:14.000000000 +0900
+++ src/emacs.c	2008-05-26 23:33:50.355468800 +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-05-26 23:33:50.385512000 +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-05-26 23:33:50.415555200 +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-05-28 01:14:30.334352800 +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
+#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,65 @@
   return _unlink (path);
 }
 
+/* deverted from delete-file in fileio.c */
+DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash,
+       Ssystem_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;
+    /* +1 means space for NULL character representing the end of the
+       final name to indicate the pFrom member of struct SHFILEOPSTRUCT */
+    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 +4207,12 @@
   return FALSE;
 }
 
+void
+syms_of_w32 ()
+{
+  defsubr (&Ssystem_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-05-26 23:33:50.485656000 +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);

^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: patch about moving file (or directory) to the Recycle Bin on Windows NT series
@ 2008-04-25 21:10 Toru TSUNEYOSHI
  2008-04-26  7:25 ` Eli Zaretskii
  2008-05-25  1:24 ` Stefan Monnier
  0 siblings, 2 replies; 24+ messages in thread
From: Toru TSUNEYOSHI @ 2008-04-25 21:10 UTC (permalink / raw)
  To: emacs-devel

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

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

[-- 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: 5811 bytes --]

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

^ permalink raw reply	[flat|nested] 24+ messages in thread
[parent not found: <BAY121-DAV73ED6DDCDAB11014BA9E6E2E10@phx.gbl>]

end of thread, other threads:[~2008-05-27 18:39 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
  -- 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
     [not found] <BAY121-DAV73ED6DDCDAB11014BA9E6E2E10@phx.gbl>
     [not found] ` <480CC2D7.3030302@gmail.com>
2008-04-21 17:07   ` Toru TSUNEYOSHI

Code repositories for project(s) associated with this public inbox

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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).