emacs-devel
[Top][All Lists]
Advanced

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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]