comparison lisp/hm--html-menus/internal-drag-and-drop.el @ 98:0d2f883870bc r20-1b1

Import from CVS: tag r20-1b1
author cvs
date Mon, 13 Aug 2007 09:13:56 +0200
parents 131b0175ea99
children 9f59509498e1
comparison
equal deleted inserted replaced
97:498bf5da1c90 98:0d2f883870bc
1 ;;; $Id: internal-drag-and-drop.el,v 1.1.1.1 1996/12/18 22:43:20 steve Exp $ 1 ;;; $Id: internal-drag-and-drop.el,v 1.2 1997/02/15 22:21:05 steve Exp $
2 ;;; 2 ;;;
3 ;;; Copyright (C) 1996 Heiko Muenkel 3 ;;; Copyright (C) 1996, 1997 Heiko Muenkel
4 ;;; email: muenkel@tnt.uni-hannover.de 4 ;;; email: muenkel@tnt.uni-hannover.de
5 ;;; 5 ;;;
6 ;;; This program is free software; you can redistribute it and/or modify 6 ;;; This program is free software; you can redistribute it and/or modify
7 ;;; it under the terms of the GNU General Public License as published by 7 ;;; it under the terms of the GNU General Public License as published by
8 ;;; the Free Software Foundation; either version 1, or (at your option) 8 ;;; the Free Software Foundation; either version 1, or (at your option)
22 ;;; 22 ;;;
23 ;;; This package provides functions to define and call internal 23 ;;; This package provides functions to define and call internal
24 ;;; drag and drop actions in the emacs. One could start such an 24 ;;; drag and drop actions in the emacs. One could start such an
25 ;;; action by clicking with the mouse in the source buffer and 25 ;;; action by clicking with the mouse in the source buffer and
26 ;;; then in the destination buffer. The action could depend on 26 ;;; then in the destination buffer. The action could depend on
27 ;;; the points where youve clicked with the mouse, on the state 27 ;;; the points where you've clicked with the mouse, on the state
28 ;;; of the region, the point, the mark and any other properties 28 ;;; of the region, the point, the mark and any other properties
29 ;;; of the source and the destination buffers. The actions are 29 ;;; of the source and the destination buffers. The actions are
30 ;;; defined by the variable `idd-actions', which is a buffer local 30 ;;; defined by the variable `idd-actions', which is a buffer local
31 ;;; variable. The following is an example for the html-mode: 31 ;;; variable. The following is an example for the hm--html-mode:
32 ;;; (defvar html-idd-actions 32 ;;; (defvar hm--html-idd-actions
33 ;;; '((nil (((idd-major-mode-p . dired-mode) 33 ;;; '((nil (((idd-if-major-mode-p . dired-mode)
34 ;;; (idd-dired-file-on-line-p . ".*\\.\\(gif\\)\\|\\(jpq\\)")) 34 ;;; (idd-if-dired-file-on-line-p
35 ;;; . ".*\\.\\(gif\\)\\|\\(jpq\\)"))
35 ;;; hm--html-idd-add-include-image-from-dired-line) 36 ;;; hm--html-idd-add-include-image-from-dired-line)
36 ;;; (((idd-major-mode-p . dired-mode) 37 ;;; (((idd-if-major-mode-p . dired-mode)
37 ;;; (idd-dired-no-file-on-line-p . nil)) 38 ;;; (idd-if-dired-no-file-on-line-p . nil))
38 ;;; hm--html-idd-add-file-link-to-file-on-dired-line) 39 ;;; hm--html-idd-add-file-link-to-file-on-dired-line)
39 ;;; (((idd-major-mode-p . dired-mode) 40 ;;; (((idd-if-major-mode-p . dired-mode)
40 ;;; (idd-dired-no-file-on-line-p . t)) 41 ;;; (idd-if-dired-no-file-on-line-p . t))
41 ;;; hm--html-idd-add-file-link-to-directory-of-buffer) 42 ;;; hm--html-idd-add-file-link-to-directory-of-buffer)
42 ;;; (((idd-major-mode-p . w3-mode) 43 ;;; (((idd-if-major-mode-p . w3-mode)
43 ;;; (idd-url-at-point-p . t)) 44 ;;; (idd-if-url-at-point-p . t))
44 ;;; hm--html-idd-add-html-link-from-w3-buffer-point) 45 ;;; hm--html-idd-add-html-link-from-w3-buffer-point)
45 ;;; (((idd-major-mode-p . w3-mode)) 46 ;;; (((idd-if-major-mode-p . w3-mode))
46 ;;; hm--html-idd-add-html-link-to-w3-buffer) 47 ;;; hm--html-idd-add-html-link-to-w3-buffer)
47 ;;; (((idd-local-file-p . t)) 48 ;;; (((idd-if-local-file-p . t))
48 ;;; hm--html-idd-add-file-link-to-buffer))) 49 ;;; hm--html-idd-add-file-link-to-buffer)))
49 ;;; Look at the variable `idd-actions' for further descriptions. 50 ;;; Look at the variable `idd-actions' for further descriptions.
50 ;;; 51 ;;;
51 ;;; 52 ;;;
52 ;;; 53 ;;;
58 ;;; (autoload 'idd-mouse-drag-and-drop "internal-drag-and-drop" 59 ;;; (autoload 'idd-mouse-drag-and-drop "internal-drag-and-drop"
59 ;;; "Performs a drag and drop action. 60 ;;; "Performs a drag and drop action.
60 ;;; At first you must click on the source and 61 ;;; At first you must click on the source and
61 ;;; after that on the destination." 62 ;;; after that on the destination."
62 ;;; t) 63 ;;; t)
63 ;;; (define-key global-map [(meta button1)] 'idd-mouse-drag-and-drop)
64 ;;; 64 ;;;
65 ;;; Define actions in the variable `idd-actions'. 65 ;;; Define actions in the variable `idd-actions'.
66 ;;; 66 ;;;
67 67 ;;; The variable `idd-global-mouse-keys' defines the mouse keys,
68 (defvar idd-actions nil 68 ;;; which are bound to the drag and drop command.
69 ;;;
70 ;;; The variable `idd-drag-and-drop-mouse-binding-type' determines
71 ;;; if you've to hold a mouse button down during moving the mouse
72 ;;; from the source to the destination or not.
73 ;;;
74
75 (require 'adapt)
76 (require 'cl)
77
78 (defvar idd-global-mouse-keys (if (adapt-emacs19p)
79 [(meta control mouse-1)]
80 [(meta control button1)])
81 "The mouse keys for the command `idd-mouse-drag-and-drop'.
82 The command `idd-mouse-drag-and-drop' is bound during the loading
83 of the package internal-drag-and-drop to this keys in the global
84 key map.
85
86 Set it to nil, if you don't want to bind this function during loading.
87
88 If the command is already bound in the global keymap during loading,
89 then this key sequence will not be bind.")
90
91 (defvar idd-global-help-mouse-keys (if (adapt-emacs19p)
92 [(meta control mouse-3)]
93 [(meta control button3)])
94 "The mouse keys for the command `idd-help-mouse-drag-and-drop'.
95 The command `idd-mouse-drag-and-drop' is bound during the loading
96 of the package internal-drag-and-drop to this keys in the global
97 key map.
98
99 Set it to nil, if you don't want to bind this function during loading.
100
101 If the command is already bound in the global keymap during loading,
102 then this key sequence will not be bind.")
103
104 (defvar idd-drag-and-drop-mouse-binding-type 'click
105 "*The type of the drag and drop mouse binding.
106 The value maybe `click or 'press-button-during-move.
107 A value of `click means, that you've to click over the source, leave
108 the button and click it again over the destination.
109 A value of 'press-button-during-move means, that you've to press
110 the button down over the source and hold it until the mouse pointer
111 is over the destination.
112
113 The disadvantage of the `press-button-during-move' type compared with
114 the `click' type is, that you can't select a destination region and
115 therefore a drag and drop action depending on a selected region can't
116 be started with that type of mouse binding.")
117
118 (defvar idd-actions '((((idd-if-region-active-p . nil))
119 (((idd-if-region-active-p . t))
120 idd-action-copy-region))
121
122 (((idd-if-region-active-p . t))
123 (((idd-if-region-active-p . t))
124 idd-action-copy-replace-region))
125
126 (((idd-if-region-active-p . nil)
127 (idd-if-modifiers-p . nil))
128 (((idd-if-region-active-p . t))
129 idd-action-move-region))
130
131 (((idd-if-region-active-p . t)
132 (idd-if-modifiers-p . nil))
133 (((idd-if-region-active-p . t))
134 idd-action-move-replace-region))
135 )
69 "The list with actions, depending on the source and the destination. 136 "The list with actions, depending on the source and the destination.
70 The list looks like: 137 The list looks like:
71 '((<source-specification-1> (<destination-specification-1> <action-1-1>) 138 '((<destination-specification-1> (<source-specification-1> <action-1-1>)
72 (<destination-specification-2> <action-1-2>) 139 (<source-specification-2> <action-1-2>)
73 : 140 :
74 ) 141 )
75 (<source-specification-2> (<destination-specification-1> <action-2-1>) 142 (<destination-specification-2> (<source-specification-1> <action-2-1>)
76 (<destination-specification-2> <action-2-2>) 143 (<source-specification-2> <action-2-2>)
77 : 144 :
78 ) 145 )
79 : 146 :
80 ) 147 )
81 The <source-specification> looks like the following: 148 The <source-specification> looks like the following:
82 '([(<specification-type> <value>)]) 149 '([(<specification-type> <value>)])
83 with <specification-type> :== idd-minor-mode-p | idd-buffer-name-p 150 with <specification-type> :== idd-if-minor-mode-p | idd-if-buffer-name-p
84 | idd-region-active-p ... 151 | idd-if-region-active-p | idd-if-url-at-point-p
85 152 | idd-if-major-mode-p | idd-if-variable-non-nil-p
86 The <destination-specification> looks like <source-specification>, except 153 | idd-if-dired-file-on-line-p
87 that a valid <specification-type> is also idd-major-mode-p. 154 | idd-if-dired-no-file-on-line-p
88 155 | idd-if-local-file-p | idd-if-buffer-name-p
89 If <source-specification-1> or <destination-specification-1> is set to 156 | idd-if-modifiers-p | ...
90 nil, then every source or destination matches. `idd-actions' is a 157
158 The <specification-type> - functions must have two arguments, the first one
159 is the source or destination and the second is the <value>. It must return
160 nil, if the test wasn't successfull and a number (in general 1), which
161 specifies the weight of the test function. The weights of all single tests
162 are added to a summary weight and assigned to the action. The action
163 with the highest weight is called from the action handler. Look at
164 the definition of `idd-if-major-mode-p', `idd-if-minor-mode-p' and so on for
165 examples. Look at the function `idd-get-source-or-destination-alist', if
166 you wan't to know the structure of the 'source-or-destination' argument
167 of these functions.
168
169 The <destination-specification> looks like <source-specification>,
170 but in general it could be set to nil in mode specific idd-action
171 lists.
172
173 If <destination-specification-1> or <source-specification-1> is set to
174 nil, then every source or source matches. `idd-actions' is a
91 buffer local variable, which should be at least mode depended. So if 175 buffer local variable, which should be at least mode depended. So if
92 the <source-specification-1> is set to nil it says, that the source 176 the <destination-specification-1> is set to nil it says, that the destination
93 buffer must only have a specific mode. But however, it's also possible 177 buffer must only have a specific mode. But however, it's also possible
94 to define a general `idd-actions' list, where the source mode is 178 to define a general `idd-actions' list, where the destination mode is
95 specified by idd-major-mode-p. 179 specified by `idd-if-major-mode-p'.
96 180
97 <action> ist a function, which has two arguments, the specifies the 181 <action> ist a function, which has two arguments, the first specifies the
98 source and the second the destination.") 182 source and the second the destination. Look at the function definition
183 of `idd-action-copy-region' and `idd-action-copy-replace-region'. They are
184 examples for such actions.")
99 185
100 (make-variable-buffer-local 'idd-actions) 186 (make-variable-buffer-local 'idd-actions)
187
188 (defvar idd-help-instead-of-action nil
189 "*If this variable is t, then a help buffer is displayed.
190 No action will be performed if this variable is t.")
191
192 (defvar idd-help-start-action-keymap nil
193 "Keymap used in an extent in the help buffer to start the action.")
194
195 (defvar idd-help-source nil
196 "Contains the source of an action. Used only in the help buffer.")
197
198 (defvar idd-help-destination nil
199 "Contains the destination of an action. Used only in the help buffer.")
200
201 (defvar idd-help-start-extent nil
202 "The start extent in the help buffer.")
101 203
102 (defun idd-compare-a-specification (source-or-destination 204 (defun idd-compare-a-specification (source-or-destination
103 specification) 205 specification)
104 "Tests if SOURCE-OR-DESTINATION matches the SPECIFICATION. 206 "Tests if SOURCE-OR-DESTINATION matches the SPECIFICATION.
105 It returns a value (1 in general) if both are matching or nil." 207 It returns a value (1 in general) if both are matching or nil."
106 (eval (list (car specification) 208 (eval (list (car specification)
107 'source-or-destination 209 'source-or-destination
108 '(cdr specification)))) 210 '(cdr specification))))
109 211
110 (defun idd-compare-specifications-1 (source-or-destination 212 (defun idd-compare-specifications-1 (source-or-destination
111 specifications 213 specifications
112 value) 214 value)
113 "Internal function of `idd-compare-specifications'. 215 "Internal function of `idd-compare-specifications'.
114 VALUE is the value of the last matches." 216 VALUE is the value of the last matches."
115 (cond ((not specifications) value) 217 (cond ((not specifications) value)
116 (t (let ((match (idd-compare-a-specification source-or-destination 218 (t (let ((match (idd-compare-a-specification source-or-destination
117 (car specifications)))) 219 (car specifications))))
119 (t (idd-compare-specifications-1 source-or-destination 221 (t (idd-compare-specifications-1 source-or-destination
120 (cdr specifications) 222 (cdr specifications)
121 (+ value match)))))))) 223 (+ value match))))))))
122 224
123 (defun idd-compare-specifications (source-or-destination 225 (defun idd-compare-specifications (source-or-destination
124 specifications) 226 specifications)
125 "Determines how good SOURCE-OR-DESTINATION and SPECIFICATIONS are matching. 227 "Determines how good SOURCE-OR-DESTINATION and SPECIFICATIONS are matching.
126 A return value of zero means, that they don't match. The higher the 228 A return value of zero means, that they don't match. The higher the
127 return value the better is the matching." 229 return value the better is the matching."
128 (cond ((not specifications) 1) 230 (cond ((not specifications) 1)
129 (t (idd-compare-specifications-1 source-or-destination 231 (t (idd-compare-specifications-1 source-or-destination
130 specifications 232 specifications
131 0)))) 233 0))))
132 234
133 (defun idd-get-action-depending-on-destination (destination 235 (defun idd-get-action-depending-on-source (source
134 actions-depending-on-dest 236 actions-depending-on-source
135 source-value 237 destination-value
136 value-action-pair) 238 value-action-pair)
137 "Internal function of `idd-get-action-depending-on-source-and-destination'." 239 "Internal function of `idd-get-action-depending-on-source-and-destination'."
138 (let ((destination-value (idd-compare-specifications 240 (let ((source-value (idd-compare-specifications
139 destination 241 source
140 (car (car actions-depending-on-dest))))) 242 (car (car actions-depending-on-source)))))
141 (cond ((not actions-depending-on-dest) value-action-pair) 243 (cond ((not actions-depending-on-source) value-action-pair)
142 ((or (= destination-value 0) 244 ((or (= source-value 0)
143 (<= (+ source-value destination-value) (car value-action-pair))) 245 (<= (+ destination-value source-value) (car value-action-pair)))
144 (idd-get-action-depending-on-destination 246 (idd-get-action-depending-on-source
145 destination 247 source
146 (cdr actions-depending-on-dest) 248 (cdr actions-depending-on-source)
147 source-value 249 destination-value
148 value-action-pair)) 250 value-action-pair))
149 (t (idd-get-action-depending-on-destination 251 (t (idd-get-action-depending-on-source
150 destination 252 source
151 (cdr actions-depending-on-dest) 253 (cdr actions-depending-on-source)
152 source-value 254 destination-value
153 (cons (+ source-value destination-value) 255 (cons (+ destination-value source-value)
154 (second (car actions-depending-on-dest)))))))) 256 (second (car actions-depending-on-source))))))))
155 257
156 (defun idd-get-action-depending-on-source-and-destination (source 258 (defun idd-get-action-depending-on-source-and-destination (source
157 destination 259 destination
158 actions 260 actions
159 value-action-pair) 261 value-action-pair)
160 "Internal function of `idd-get-action'. 262 "Internal function of `idd-get-action'.
161 VALUE-ACTION-PAIR is a list like (<value> <action>). 263 VALUE-ACTION-PAIR is a list like (<value> <action>).
162 It returns VALUE-ACTION-PAIR, if no other action is found, which has a 264 It returns VALUE-ACTION-PAIR, if no other action is found, which has a
163 value higher than (car VALUE-ACTION-PAIR)." 265 value higher than (car VALUE-ACTION-PAIR)."
164 (let ((source-value (idd-compare-specifications source (car (car actions))))) 266 (let ((destination-value
267 (idd-compare-specifications destination (car (car actions)))))
165 (cond ((not actions) value-action-pair) 268 (cond ((not actions) value-action-pair)
166 ((= source-value 0) 269 ((= destination-value 0)
167 (idd-get-action-depending-on-source-and-destination 270 (idd-get-action-depending-on-source-and-destination
168 source 271 source
169 destination 272 destination
170 (cdr actions) 273 (cdr actions)
171 value-action-pair)) 274 value-action-pair))
172 (t (idd-get-action-depending-on-source-and-destination 275 (t (idd-get-action-depending-on-source-and-destination
173 source 276 source
174 destination 277 destination
175 (cdr actions) 278 (cdr actions)
176 (idd-get-action-depending-on-destination 279 (idd-get-action-depending-on-source
177 destination 280 source
178 (cdr (car actions)) 281 (cdr (car actions))
179 source-value 282 destination-value
180 value-action-pair)))))) 283 value-action-pair))))))
181 284
182 (defun idd-get-action (source destination actions) 285 (defun idd-get-action (source destination actions)
183 "Returns the action, which depends on the SOURCE and the DESTINATION. 286 "Returns the action, which depends on the SOURCE and the DESTINATION.
184 The list ACTIONS contains all possible actions. Look at the variable 287 The list ACTIONS contains all possible actions. Look at the variable
186 (idd-get-action-depending-on-source-and-destination source 289 (idd-get-action-depending-on-source-and-destination source
187 destination 290 destination
188 actions 291 actions
189 '(0 . nil))) 292 '(0 . nil)))
190 293
294 (autoload 'ange-ftp-ftp-path "ange-ftp"
295 "Parse PATH according to ange-ftp-path-format (which see).
296 Returns a list (HOST USER PATH), or nil if PATH does not match the format.")
297
298 (defun idd-set-point (source-or-destination)
299 "Sets the point and buffer to SOURCE-OR-DESTINATION."
300 (set-buffer (cdr (assoc ':buffer source-or-destination)))
301 (goto-char (cdr (assoc ':drag-or-drop-point source-or-destination))))
302
303 (defun idd-set-region (source-or-destination)
304 "Sets the point, mark and buffer to SOURCE-OR-DESTINATION.
305 The region is active after this function is called."
306 (set-buffer (cdr (assoc ':buffer source-or-destination)))
307 (goto-char (car (cdr (assoc ':region-active source-or-destination))))
308 (set-mark (cdr (cdr (assoc ':region-active source-or-destination))))
309 (activate-region))
310
311
312 ;;; Specification type functions for the list `idd-actions'
313
314 (defun idd-if-region-active-p (source-or-destination value)
315 "Checks if the region in the SOURCE-OR-DESTINATION was active.
316 It returns 1, if the region was active and VALUE is t, or if
317 the region was not active and VALUE is nil. Otherwise it returns
318 nil."
319 (if (cdr (assoc ':region-active source-or-destination))
320 (if value 1 nil)
321 (if value nil 1)))
322
191 (defun idd-get-buffer-url (source-or-destination) 323 (defun idd-get-buffer-url (source-or-destination)
192 "Returns the URL of the buffer specified by SOURCE-OR-DESTINATION." 324 "Returns the URL of the buffer specified by SOURCE-OR-DESTINATION."
193 (save-excursion 325 (save-excursion
194 (idd-set-point source-or-destination) 326 (idd-set-point source-or-destination)
195 (url-view-url t))) 327 (url-view-url t)))
199 It returns nil, if there is no URL." 331 It returns nil, if there is no URL."
200 (save-excursion 332 (save-excursion
201 (idd-set-point source-or-destination) 333 (idd-set-point source-or-destination)
202 (w3-view-this-url t))) 334 (w3-view-this-url t)))
203 335
204 (defun idd-url-at-point-p (source-or-destination value) 336 (defun idd-if-url-at-point-p (source-or-destination value)
205 "Checks if there is an URL at the point of SOURCE-OR-DESTINATION. 337 "Checks if there is an URL at the point of SOURCE-OR-DESTINATION.
206 If that is t and VALUE is t, or that is nil and VALUE is nil, then 1 338 If that is t and VALUE is t, or that is nil and VALUE is nil, then 1
207 is returned. Otherwise nil is returned." 339 is returned. Otherwise nil is returned."
208 (if value 340 (if value
209 (if (idd-get-url-at-point source-or-destination) 341 (if (idd-get-url-at-point source-or-destination)
211 nil) 343 nil)
212 (if (idd-get-url-at-point source-or-destination) 344 (if (idd-get-url-at-point source-or-destination)
213 nil 345 nil
214 1))) 346 1)))
215 347
216 (defun idd-major-mode-p (source-or-destination mode) 348 (defun idd-if-major-mode-p (source-or-destination mode)
217 "Checks, if the major mode of SOURCE-OR-DESTINATION is MODE. 349 "Checks, if the major mode of SOURCE-OR-DESTINATION is MODE.
218 It returns 1, if that is t and nil otherwise." 350 It returns 1, if that is t and nil otherwise."
219 (save-excursion 351 (save-excursion
220 (set-buffer (cdr (assoc ':buffer source-or-destination))) 352 (set-buffer (cdr (assoc ':buffer source-or-destination)))
221 (if (eq major-mode mode) 353 (if (eq major-mode mode)
222 1 354 1
223 nil))) 355 nil)))
224 356
225 (defun idd-set-point (source-or-destination) 357 (defun idd-if-variable-non-nil-p (source-or-destination variable)
226 "Sets the point and buffer to SOURCE-OR-DESTINATION." 358 "Checks, if the variable named VARIABLE isn't t in SOURCE-OR-DESTINATION.
227 (set-buffer (cdr (assoc ':buffer source-or-destination))) 359 It returns 1, if this is t."
228 (goto-char (cdr (assoc ':drag-or-drop-point source-or-destination)))) 360 (save-excursion
229 361 (set-buffer (cdr (assoc ':buffer source-or-destination)))
230 (defun idd-set-region (source-or-destination) 362 (if (eval variable)
231 "Sets the point, mark and buffer to SOURCE-OR-DESTINATION. 363 1
232 The region is active after this function is called." 364 nil)))
233 (set-buffer (cdr (assoc ':buffer source-or-destination))) 365
234 (goto-char (car (cdr (assoc ':region-active source-or-destination)))) 366 (defun idd-if-minor-mode-p (source-or-destination minor-mode-variable)
235 (set-mark (cdr (cdr (assoc ':region-active source-or-destination)))) 367 "Checks, if the variable MINOR-MODE-VARIABLE is t in SOURCE-OR-DESTINATION.
236 (activate-region)) 368 MINOR-MODE-VARIABLE is the name of the variable!."
369 (idd-variable-non-nil-p source-or-destination minor-mode-variable))
237 370
238 (defun idd-get-dired-filename-from-line (source-or-destination) 371 (defun idd-get-dired-filename-from-line (source-or-destination)
239 "Returns the filename form the line in a dired buffer. 372 "Returns the filename form the line in a dired buffer.
240 The position and the buffer is specified by SOURCE-OR-DESTINATION." 373 The position and the buffer is specified by SOURCE-OR-DESTINATION."
241 (save-excursion 374 (save-excursion
242 (idd-set-point source-or-destination) 375 (idd-set-point source-or-destination)
243 (dired-get-filename nil t))) 376 (dired-get-filename nil t)))
244 377
245 (defun idd-dired-file-on-line-p (source-or-destination filename-regexp) 378 (defun idd-if-dired-file-on-line-p (source-or-destination filename-regexp)
246 "Checks, if the filename on the line match FILENAME-REGEXP. 379 "Checks, if the filename on the line match FILENAME-REGEXP.
247 The function `dired-get-filename' is used, to get the filename from 380 The function `dired-get-filename' is used, to get the filename from
248 the SOURCE-OR-DESTINATION. It returns 1, if it matchs or nil." 381 the SOURCE-OR-DESTINATION. It returns 1, if it matchs or nil."
249 (let ((case-fold-search t)) 382 (let ((case-fold-search t))
250 (if (and (idd-get-dired-filename-from-line source-or-destination) 383 (if (and (idd-get-dired-filename-from-line source-or-destination)
252 (idd-get-dired-filename-from-line 385 (idd-get-dired-filename-from-line
253 source-or-destination))) 386 source-or-destination)))
254 1 387 1
255 nil))) 388 nil)))
256 389
257 (defun idd-dired-no-file-on-line-p (source-or-destination value) 390 (defun idd-if-dired-no-file-on-line-p (source-or-destination value)
258 "Checks, if a filename is in the dired buffer of SOURCE-OR-DESTINATION. 391 "Checks, if a filename is in the dired buffer of SOURCE-OR-DESTINATION.
259 It returns 1, if a filename is on the line and if VALUE is t, or if 392 It returns 1, if a filename is on the line and if VALUE is t, or if
260 no filename is on the line and VALUE is nil, otherwise it returns 393 no filename is on the line and VALUE is nil, otherwise it returns
261 nil. For the test the function `dired-get-filename' is used." 394 nil. For the test the function `dired-get-filename' is used."
262 (if (idd-get-dired-filename-from-line source-or-destination) 395 (if (idd-get-dired-filename-from-line source-or-destination)
263 (if value nil 1) 396 (if value nil 1)
264 (if value 1 nil))) 397 (if value 1 nil)))
265 398
266 (autoload 'ange-ftp-ftp-path "ange-ftp"
267 "Parse PATH according to ange-ftp-path-format (which see).
268 Returns a list (HOST USER PATH), or nil if PATH does not match the format.")
269
270 (defun idd-get-local-filename (source-or-destination) 399 (defun idd-get-local-filename (source-or-destination)
271 "Returns the filename of a local file specified by SOURCE-OR-DESTINATION." 400 "Returns the filename of a local file specified by SOURCE-OR-DESTINATION."
272 (buffer-file-name (cdr (assoc ':buffer source-or-destination)))) 401 (buffer-file-name (cdr (assoc ':buffer source-or-destination))))
273 402
274 (defun idd-get-directory-of-buffer (source-or-destination) 403 (defun idd-get-directory-of-buffer (source-or-destination)
275 "Returns the directory name assigned to the SOURCE-OR-DESTINATION buffer." 404 "Returns the directory name assigned to the SOURCE-OR-DESTINATION buffer."
276 (save-excursion 405 (save-excursion
277 (idd-set-point source-or-destination) 406 (idd-set-point source-or-destination)
278 default-directory)) 407 default-directory))
279 408
280 (defun idd-local-file-p (source-or-destination value) 409 (defun idd-if-local-file-p (source-or-destination value)
281 "Checks, if SOURCE-OR-DESTINATION has a file on the local filesystem. 410 "Checks, if SOURCE-OR-DESTINATION has a file on the local filesystem.
282 If that is t and VALUE is t, or that is nil and VALUE is nil, then 1 411 If that is t and VALUE is t, or that is nil and VALUE is nil, then 1
283 is returned. Otherwise nil is returned." 412 is returned. Otherwise nil is returned."
284 (let ((filename (idd-get-local-filename source-or-destination))) 413 (let ((filename (idd-get-local-filename source-or-destination)))
285 (if (and filename 414 (if (and filename
286 (not (ange-ftp-ftp-path filename))) 415 (not (ange-ftp-ftp-path filename)))
287 (if value 1 nil) 416 (if value 1 nil)
288 (if value nil 1)))) 417 (if value nil 1))))
289 418
419 (defun idd-if-buffer-name-p (source-or-destination buffer-name)
420 "Checks, if SOURCE-OR-DESTINATION has a buffer called BUFFER-NAME.
421 It returns 1 if this is the case or nil otherwise."
422 (if (string= buffer-name
423 (buffer-name (cdr (assoc ':buffer source-or-destination))))
424 1
425 nil))
426
427 (defun idd-list-1-subset-of-list-2 (list-1 list-2)
428 "Returns t, if LIST-1 is a subset of LIST-2."
429 (cond ((not list-1))
430 ((member (car list-1 list-2))
431 (idd-list-1-subset-of-list-2 (cdr list-1) list-2))
432 (t nil)))
433
434 (defun idd-same-modifiers (list-1 list-2)
435 "Returns t, if both list have the same modifiers."
436 (and (length list-1 list-2)
437 (idd-list-1-subset-of-list-2 list-1-list-2)))
438
439 (defun idd-if-modifiers-p (source-or-destination modifiers)
440 "Checks, if the MODIFIERS hold during selecting the SOURCE-OR-DESTINATION.
441 Returns 1, if the list MODIFIERS contains the same modifiers,
442 or if any modyfiers are hold and MODIFIERS is t,
443 or if no modyfiers are hold and MODIFIERS is nil.
444 Otherwise nil is returned."
445 (let ((event-modifiers (event-modifiers
446 (cdr (assoc ':event source-or-destination)))))
447 (cond ((not modifiers)
448 (if event-modifiers nil 1))
449 ((listp modifiers)
450 (if (idd-same-elements modifiers event-modifiers)
451 1
452 nil))
453 (t (if event-modifiers 1 nil)))))
454
455 ;;; action functions
456
457 (defun idd-action-copy-region (source destination)
458 "Copy the region from DESTINATION to SOURCE."
459 (idd-set-region source)
460 (let ((region-contents (buffer-substring (point) (mark))))
461 (idd-set-point destination)
462 (insert region-contents)))
463
464 (defun idd-action-copy-replace-region (source destination)
465 "Copy the region from SOURCE and replace the DESTINATION region with it."
466 (idd-set-region source)
467 (let ((region-contents (buffer-substring (point) (mark))))
468 (idd-set-region destination)
469 (delete-region (point) (mark))
470 (insert region-contents)))
471
472 (defmacro* idd-with-source-and-destination (source
473 destination
474 &key
475 do-in-source
476 do-in-destination)
477 "Macro, usefull for the definition of action functions.
478 Look at the example `idd-action-move-region'."
479 `(progn
480 (if (idd-if-region-active-p ,source t)
481 (idd-set-region ,source)
482 (idd-set-point ,source))
483 ,(when do-in-source
484 (cons 'progn do-in-source))
485 (if (idd-if-region-active-p ,destination t)
486 (idd-set-region ,destination)
487 (idd-set-point ,destination))
488 ,(when do-in-destination
489 (cons 'progn do-in-destination))))
490
491 (defun idd-action-move-region (source destination)
492 "Move the region from SOURCE to DESTINATION."
493 (let ((region))
494 (idd-with-source-and-destination
495 source destination
496 :do-in-source ((setq region (buffer-substring (point) (mark)))
497 (delete-region (point) (mark)))
498 :do-in-destination ((insert region)))))
499
500
501 (defun idd-action-move-replace-region (source destination)
502 "Delete the region at SOURCE and overwrite the DESTINATION region with it."
503 (let ((region))
504 (idd-with-source-and-destination
505 source destination
506 :do-in-source ((setq region (buffer-substring (point) (mark)))
507 (delete-region (point) (mark)))
508 :do-in-destination ((delete-region (point) (mark))
509 (insert region)))))
510
511
512 ;;; Performing the drag and drop
513
514 (defun idd-display-help-about-action (action source destination)
515 "Display a help buffer with information about the action."
516 (if (> (car action) 0)
517 (if (symbol-function (cdr action))
518 (progn
519 (with-displaying-help-buffer
520 '(lambda ()
521 (set-buffer "*Help*")
522 (setq idd-help-source source)
523 (setq idd-help-destination destination)
524 (insert "Drag and drop action: `")
525 (let ((start (point)))
526 (insert (format "%s" (cdr action)))
527 (setq idd-help-start-extent (make-extent start (point)))
528 (set-extent-mouse-face idd-help-start-extent 'highlight)
529 (set-extent-face idd-help-start-extent 'bold)
530 (set-extent-keymap idd-help-start-extent
531 idd-help-start-action-keymap)
532 )
533 (insert "'\n")
534 (insert (format "Source buffer : `%s'\n"
535 (buffer-name (cdr (assoc ':buffer source)))))
536 (insert (format "Destination buffer : `%s'\n"
537 (buffer-name (cdr (assoc ':buffer destination))
538 )))
539 (insert "=================================================="
540 "====================\n")
541 (insert "Look at `idd-actions' in the "
542 "destination buffer for other actions!\n")
543 (insert (format "The documentation of `%s':\n\n"
544 (cdr action)))
545 (insert (documentation (cdr action)))))
546 )
547 (error "Error: Action %s isn't a valid function!" (cdr action)))
548 (message "No valid action defined for this source and this destination!")))
549
290 (defun idd-call-action (action source destination) 550 (defun idd-call-action (action source destination)
291 "Calls the drag and drop ACTION with its arguments SOURCE and DESTINATION." 551 "Calls the drag and drop ACTION with its arguments SOURCE and DESTINATION."
292 (if (> (car action) 0) 552 (if (> (car action) 0)
293 (if (symbol-function (cdr action)) 553 (if (symbol-function (cdr action))
294 (eval (list (cdr action) 'source 'destination)) 554 (eval (list (cdr action) 'source 'destination))
295 (error "Error: Action %s isn't a valid function!" (cdr action))) 555 (error "Error: Action %s isn't a valid function!" (cdr action)))
296 (message "No valid action defined for this source and this destination!"))) 556 (message "No valid action defined for this source and this destination!")))
297 557
558 (defun idd-start-help-mouse-drag-and-drop ()
559 "Starts help on `idd-start-mouse-drag-and-drop'."
560 (interactive)
561 (let ((idd-help-instead-of-action t))
562 (idd-start-mouse-drag-and-drop)))
563
564 (defun idd-start-mouse-drag-and-drop ()
565 "Starts a drag and drop command.
566 This command could be used to start a drag and drop command without a
567 button event. Therefore this should not be bind direct to a mouse button."
568 (interactive)
569 (let ((destination-event)
570 (drag-and-drop-message "Drag&Drop: Click on the source!"))
571 (message drag-and-drop-message)
572 (setq source-event
573 (next-command-event nil drag-and-drop-message))
574 (if (button-press-event-p source-event)
575 (idd-mouse-drag-and-drop source-event)
576 (message "Wrong event! Exit drag and drop."))))
577
578 (defun idd-help-mouse-drag-and-drop (source-event)
579 "Displays help about the drag and drop action."
580 (interactive "@e")
581 (let ((idd-help-instead-of-action t))
582 (idd-mouse-drag-and-drop source-event)))
583
298 (defun idd-mouse-drag-and-drop (source-event) 584 (defun idd-mouse-drag-and-drop (source-event)
299 "Performs a drag and drop action. 585 "Performs a drag and drop action.
300 At first you must click on the source and after that on the destination." 586 It calls the command `idd-mouse-drag-and-drop-click' or
587 `idd-mouse-drag-and-drop-press-button-during-move' depending on
588 the value of `idd-drag-and-drop-mouse-binding-type'."
301 (interactive "@e") 589 (interactive "@e")
302 (let ((source (list (cons ':buffer (current-buffer)) 590 (if (eq idd-drag-and-drop-mouse-binding-type 'click)
303 (cons ':drag-or-drop-point 591 (idd-mouse-drag-and-drop-click source-event)
304 (event-closest-point source-event)) 592 (idd-mouse-drag-and-drop-press-button-during-move source-event)))
305 (cons ':region-active (if (region-active-p) 593
306 (cons (point) 594 (defun idd-get-source-or-destination-alist (event)
307 (mark)))))) 595 "Returns an alist with the description of a source or destination point.
596 The EVENT must be the button event, which has selected the source or
597 destination of the drag and drop command.
598
599 The alist has the following structure:
600 '((:buffer . <buffer-of-the-event>)
601 (:drag-or-drop-point . <closest-point-to-the-event>)
602 (:region-active . <t-or-nil>)
603 (:event . EVENT))
604
605 Note: <closest-point-to-the-event> is (event-closest-point EVENT),
606 if the EVENT is a mouse event and if it isn't nil. Otherwise the
607 point is used."
608 ; (set-buffer (event-buffer event))
609 (list (cons ':buffer (event-buffer event))
610 (cons ':drag-or-drop-point (set-marker
611 (make-marker)
612 (if (mouse-event-p event)
613 (or (event-closest-point event)
614 (point))
615 (point))))
616 (cons ':region-active (if (region-active-p)
617 (cons (set-marker (make-marker) (point))
618 (set-marker (make-marker) (mark)))))
619 (cons ':event event))
620 )
621
622 (defun idd-mouse-drag-and-drop-press-button-during-move (source-event)
623 "Performs a drag and drop action.
624 At first you must press the button down over the source and then
625 move with the pressed button to the destination, where you must leave
626 the button up.
627 This must be bind to a mouse button. The SOURCE-EVENT must be a
628 button-press-event.
629
630 The disadvantage of this command compared with the command
631 `idd-mouse-drag-and-drop-click' is, that you can't select a
632 destination region."
633 (interactive "@e")
634 (let ((drag-and-drop-message
635 "Drag&Drop: Leave the button over the destination!")
636 (source (idd-get-source-or-destination-alist source-event))
308 (destination nil) 637 (destination nil)
309 (destination-event)) 638 (destination-event))
310 (if (adapt-xemacsp) 639 (message drag-and-drop-message)
640 (setq destination-event
641 (next-command-event nil drag-and-drop-message))
642 (message "")
643 (cond ((button-release-event-p destination-event)
644 (setq destination (idd-get-source-or-destination-alist
645 destination-event))
646 (idd-set-point destination)
647 (if idd-help-instead-of-action
648 (idd-display-help-about-action (idd-get-action source
649 destination
650 idd-actions)
651 source
652 destination)
653 (idd-call-action (idd-get-action source destination idd-actions)
654 source
655 destination)))
656 (t (message "Wrong event! Exit drag and drop.") nil))))
657
658 (defun idd-mouse-drag-and-drop-click (source-event)
659 "Performs a drag and drop action.
660 At first you must click on the source and after that on the destination.
661 This must be bind to a mouse button. The SOURCE-EVENT must be a
662 button-press-event."
663 (interactive "@e")
664 (let ((drag-and-drop-message "Drag&Drop: Click on the destination!")
665 (source (idd-get-source-or-destination-alist source-event))
666 (destination nil)
667 (destination-event))
668 (message drag-and-drop-message)
669 (if (and (adapt-xemacsp) (mouse-event-p source-event))
311 (dispatch-event (next-command-event))) 670 (dispatch-event (next-command-event)))
312 (setq destination-event 671 (setq destination-event
313 (next-command-event nil "Drag&Drop: Click on the destination!")) 672 (next-command-event nil drag-and-drop-message))
673 (setq heiko source-event)
674 (message "")
314 (cond ((button-press-event-p destination-event) 675 (cond ((button-press-event-p destination-event)
315 (setq destination (list (cons ':buffer 676 (mouse-track destination-event)
316 (event-buffer destination-event)) 677 (setq destination (idd-get-source-or-destination-alist
317 (cons ':drag-or-drop-point 678 destination-event))
318 (event-closest-point 679 (idd-set-point destination)
319 destination-event))
320 (cons ':region-active nil)))
321 (if (adapt-emacs19p) 680 (if (adapt-emacs19p)
322 (while (not (button-release-event-p (next-command-event))))) 681 (while (not (button-release-event-p (next-command-event)))))
323 (idd-call-action (idd-get-action source destination idd-actions) 682 (if idd-help-instead-of-action
324 source 683 (idd-display-help-about-action (idd-get-action source
325 destination)) 684 destination
326 (t (setq action "Wrong event") nil)))) 685 idd-actions)
686 source
687 destination)
688 (idd-call-action (idd-get-action source destination idd-actions)
689 source
690 destination)))
691 (t (message "Wrong event! Exit drag and drop.") nil))))
692
693 (defun idd-help-start-action (event)
694 "Used to start the action from the help buffer."
695 (interactive "@e")
696 (idd-set-point idd-help-destination)
697 (idd-call-action (idd-get-action idd-help-source
698 idd-help-destination
699 idd-actions)
700 idd-help-source
701 idd-help-destination)
702 (delete-extent idd-help-start-extent))
703
704 ;; keymap for help buffer extents
705 (if (not idd-help-start-action-keymap)
706 (progn
707 (setq idd-help-start-action-keymap
708 (make-sparse-keymap 'idd-help-start-action-keymap))
709 (if (adapt-emacs19p)
710 (define-key idd-help-start-action-keymap [(mouse-2)]
711 'idd-help-start-action)
712 (define-key idd-help-start-action-keymap "[(button2)]"
713 'idd-help-start-action))))
714
715 ;; global key bindings
716 (when idd-global-mouse-keys
717 (unless (where-is-internal 'idd-mouse-drag-and-drop global-map t)
718 (define-key global-map idd-global-mouse-keys 'idd-mouse-drag-and-drop))
719 (unless (where-is-internal 'idd-help-mouse-drag-and-drop global-map t)
720 (define-key global-map
721 idd-global-help-mouse-keys 'idd-help-mouse-drag-and-drop)))
327 722
328 723
329 (provide 'internal-drag-and-drop) 724 (provide 'internal-drag-and-drop)