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