;;; dnd.el --- drag and drop support.
-;; Copyright (C) 2005
-;; Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2006 Free Software Foundation, Inc.
;; Author: Jan Dj\e,Ad\e(Brv <jan.h.d@swipnet.se>
;; Maintainer: FSF
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Commentary:
;;;###autoload
(defcustom dnd-protocol-alist
- '(
- ("^file:///" . dnd-open-local-file) ; XDND format.
- ("^file://" . dnd-open-file) ; URL with host
- ("^file:" . dnd-open-local-file) ; Old KDE, Motif, Sun
- )
+ '(("^file:///" . dnd-open-local-file) ; XDND format.
+ ("^file://" . dnd-open-file) ; URL with host
+ ("^file:" . dnd-open-local-file) ; Old KDE, Motif, Sun
+ ("^\\(https?\\|ftp\\|file\\|nfs\\)://" . dnd-open-file)
+ )
"The functions to call for different protocols when a drop is made.
This variable is used by `dnd-handle-one-url' and `dnd-handle-file-name'.
:group 'dnd)
+(defcustom dnd-open-remote-file-function
+ (if (eq system-type 'windows-nt)
+ 'dnd-open-local-file
+ 'dnd-open-remote-url)
+ "The function to call when opening a file on a remote machine.
+The function will be called with two arguments; URI and ACTION. See
+`dnd-open-file' for details.
+If nil, then dragging remote files into Emacs will result in an error.
+Predefined functions are `dnd-open-local-file' and `dnd-open-remote-url'.
+`dnd-open-local-file' attempts to open a remote file using its UNC name and
+is the default on MS-Windows. `dnd-open-remote-url' uses `url-handler-mode'
+and is the default except for MS-Windows."
+ :version "22.1"
+ :type 'function
+ :group 'dnd)
+
(defcustom dnd-open-file-other-window nil
"If non-nil, always use find-file-other-window to open dropped files."
;; Functions
-(defun dnd-handle-one-url (window action arg)
+(defun dnd-handle-one-url (window action url)
"Handle one dropped url by calling the appropriate handler.
The handler is first located by looking at `dnd-protocol-alist'.
If no match is found here, and the value of `browse-url-browser-function'
is a pair of (REGEXP . FUNCTION), those regexps are tried for a match.
If no match is found, just call `dnd-insert-text'.
WINDOW is where the drop happend, ACTION is the action for the drop,
-ARG is the URL that has been dropped.
+URL is what has been dropped.
Returns ACTION."
(require 'browse-url)
- (let* ((uri (replace-regexp-in-string
- "%[A-Z0-9][A-Z0-9]"
- (lambda (arg)
- (format "%c" (string-to-number (substring arg 1) 16)))
- arg))
- ret)
+ (let (ret)
(or
(catch 'done
(dolist (bf dnd-protocol-alist)
- (when (string-match (car bf) uri)
- (setq ret (funcall (cdr bf) uri action))
+ (when (string-match (car bf) url)
+ (setq ret (funcall (cdr bf) url action))
(throw 'done t)))
nil)
(when (not (functionp browse-url-browser-function))
(catch 'done
(dolist (bf browse-url-browser-function)
- (when (string-match (car bf) uri)
+ (when (string-match (car bf) url)
(setq ret 'private)
- (funcall (cdr bf) uri action)
+ (funcall (cdr bf) url action)
(throw 'done t)))
nil))
(progn
- (dnd-insert-text window action uri)
+ (dnd-insert-text window action url)
(setq ret 'private)))
ret))
((string-match "^file:" uri) ; Old KDE, Motif, Sun
(substring uri (match-end 0))))))
(when (and f must-exist)
+ (setq f (replace-regexp-in-string
+ "%[A-Z0-9][A-Z0-9]"
+ (lambda (arg)
+ (format "%c" (string-to-number (substring arg 1) 16)))
+ f nil t))
(let* ((decoded-f (decode-coding-string
f
(or file-name-coding-system
The file is opened in the current window, or a new window if
`dnd-open-file-other-window' is set. URI is the url for the file,
and must have the format file:file-name or file:///file-name.
-The last / in file:/// is part of the file name. ACTION is ignored."
+The last / in file:/// is part of the file name. If the system
+natively supports unc file names, then remote urls of the form
+file://server-name/file-name will also be handled by this function.
+An alternative for systems that do not support unc file names is
+`dnd-open-remote-url'. ACTION is ignored."
(let* ((f (dnd-get-local-file-name uri t)))
(if (and f (file-readable-p f))
'private)
(error "Can not read %s" uri))))
+(defun dnd-open-remote-url (uri action)
+ "Open a remote file with `find-file' and `url-handler-mode'.
+Turns `url-handler-mode' on if not on before. The file is opened in the
+current window, or a new window if `dnd-open-file-other-window' is set.
+URI is the url for the file. ACTION is ignored."
+ (progn
+ (require 'url-handlers)
+ (or url-handler-mode (url-handler-mode))
+ (if dnd-open-file-other-window
+ (find-file-other-window uri)
+ (find-file uri))
+ 'private))
+
+
(defun dnd-open-file (uri action)
"Open a local or remote file.
The file is opened in the current window, or a new window if
;; file. Otherwise return nil.
(let ((local-file (dnd-get-local-file-uri uri)))
(if local-file (dnd-open-local-file local-file action)
- (error "Remote files not supported"))))
+ (if dnd-open-remote-file-function
+ (funcall dnd-open-remote-file-function uri action)
+ (error "Remote files not supported")))))
(defun dnd-insert-text (window action text)
(not (windowp window)))
(progn
(kill-new text)
- (message
+ (message "%s"
(substitute-command-keys
"The dropped text can be accessed with \\[yank]")))
(insert text))