(log-edit-changelog-full-paragraphs): Fix spellings in docstrings.
[bpt/emacs.git] / lisp / mouse.el
CommitLineData
be010748 1;;; mouse.el --- window system-independent mouse support
84176303 2
fbd8dc8a 3;; Copyright (C) 1993, 94, 95, 1999, 2000, 2001, 2002, 2003, 2004, 2005
5925bb84 4;; Free Software Foundation, Inc.
eea8d4ef 5
84176303 6;; Maintainer: FSF
de420e82 7;; Keywords: hardware, mouse
84176303 8
be010748 9;; This file is part of GNU Emacs.
72ea54a4 10
be010748
RS
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation; either version 2, or (at your option)
14;; any later version.
72ea54a4 15
be010748
RS
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
72ea54a4 20
be010748 21;; You should have received a copy of the GNU General Public License
4c9afcbe
RS
22;; along with GNU Emacs; see the file COPYING. If not, write to the
23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24;; Boston, MA 02111-1307, USA.
72ea54a4 25
edbd2f74
ER
26;;; Commentary:
27
28;; This package provides various useful commands (including help
29;; system access) through the mouse. All this code assumes that mouse
30;; interpretation has been abstracted into Emacs input events.
31;;
32;; The code is rather X-dependent.
33
aae56ea7
ER
34;;; Code:
35
cc0a8174 36;;; Utility functions.
72ea54a4 37
cc0a8174
JB
38;;; Indent track-mouse like progn.
39(put 'track-mouse 'lisp-indent-function 0)
72ea54a4 40
3b558d41
RS
41(defcustom mouse-yank-at-point nil
42 "*If non-nil, mouse yank commands yank at point instead of at click."
43 :type 'boolean
44 :group 'mouse)
b2dae92a
KS
45
46(defcustom mouse-drag-copy-region t
47 "*If non-nil, mouse drag copies region to kill-ring."
48 :type 'boolean
bf247b6e 49 :version "22.1"
b2dae92a
KS
50 :group 'mouse)
51
5dbda518 52(defcustom mouse-1-click-follows-link 450
787e24c3 53 "Non-nil means that clicking Mouse-1 on a link follows the link.
65f76581 54
787e24c3
KS
55With the default setting, an ordinary Mouse-1 click on a link
56performs the same action as Mouse-2 on that link, while a longer
57Mouse-1 click \(hold down the Mouse-1 button for more than 350
58milliseconds) performs the original Mouse-1 binding \(which
65f76581
KS
59typically sets point where you click the mouse).
60
61If value is an integer, the time elapsed between pressing and
62releasing the mouse button determines whether to follow the link
787e24c3 63or perform the normal Mouse-1 action (typically set point).
65f76581
KS
64The absolute numeric value specifices the maximum duration of a
65\"short click\" in milliseconds. A positive value means that a
66short click follows the link, and a longer click performs the
67normal action. A negative value gives the opposite behaviour.
68
69If value is `double', a double click follows the link.
70
787e24c3 71Otherwise, a single Mouse-1 click unconditionally follows the link.
65f76581
KS
72
73Note that dragging the mouse never follows the link.
74
75This feature only works in modes that specifically identify
76clickable text as links, so it may not work with some external
77packages. See `mouse-on-link-p' for details."
bf247b6e 78 :version "22.1"
65f76581
KS
79 :type '(choice (const :tag "Disabled" nil)
80 (const :tag "Double click" double)
81 (number :tag "Single click time limit" :value 350)
82 (other :tag "Single click" t))
83 :group 'mouse)
84
185a53bb
KS
85(defcustom mouse-1-click-in-non-selected-windows t
86 "*If non-nil, a Mouse-1 click also follows links in non-selected windows.
87
88If nil, a Mouse-1 click on a link in a non-selected window performs
89the normal mouse-1 binding, typically selects the window and sets
90point at the click position."
91 :type 'boolean
92 :version "22.1"
93 :group 'mouse)
94
95
cc0a8174 96\f
95132d1c
RS
97;; Provide a mode-specific menu on a mouse button.
98
21ad0f7b
SM
99(defun popup-menu (menu &optional position prefix)
100 "Popup the given menu and call the selected option.
de420e82
DL
101MENU can be a keymap, an easymenu-style menu or a list of keymaps as for
102`x-popup-menu'.
21ad0f7b
SM
103POSITION can be a click event or ((XOFFSET YOFFSET) WINDOW) and defaults to
104 the current mouse position.
105PREFIX is the prefix argument (if any) to pass to the command."
de420e82
DL
106 (let* ((map (cond
107 ((keymapp menu) menu)
108 ((and (listp menu) (keymapp (car menu))) menu)
109 (t (let* ((map (easy-menu-create-menu (car menu) (cdr menu)))
72596e2f
SM
110 (filter (when (symbolp map)
111 (plist-get (get map 'menu-prop) :filter))))
112 (if filter (funcall filter (symbol-function map)) map)))))
0dd672a6 113 event cmd)
b52a30d8 114 (unless position
d32af6dd 115 (let ((mp (mouse-pixel-position)))
b52a30d8 116 (setq position (list (list (cadr mp) (cddr mp)) (car mp)))))
21ad0f7b 117 ;; The looping behavior was taken from lmenu's popup-menu-popup
7636d2a3
EZ
118 (while (and map (setq event
119 ;; map could be a prefix key, in which case
120 ;; we need to get its function cell
121 ;; definition.
d32af6dd 122 (x-popup-menu position (indirect-function map))))
21ad0f7b
SM
123 ;; Strangely x-popup-menu returns a list.
124 ;; mouse-major-mode-menu was using a weird:
125 ;; (key-binding (apply 'vector (append '(menu-bar) menu-prefix events)))
0dd672a6
SM
126 (setq cmd
127 (if (and (not (keymapp map)) (listp map))
128 ;; We were given a list of keymaps. Search them all
129 ;; in sequence until a first binding is found.
130 (let ((mouse-click (apply 'vector event))
131 binding)
132 (while (and map (null binding))
133 (setq binding (lookup-key (car map) mouse-click))
134 (if (numberp binding) ; `too long'
135 (setq binding nil))
136 (setq map (cdr map)))
137 binding)
138 ;; We were given a single keymap.
139 (lookup-key map (apply 'vector event))))
140 ;; Clear out echoing, which perhaps shows a prefix arg.
141 (message "")
142 ;; Maybe try again but with the submap.
143 (setq map (if (keymapp cmd) cmd)))
324cd972
RS
144 ;; If the user did not cancel by refusing to select,
145 ;; and if the result is a command, run it.
146 (when (and (null map) (commandp cmd))
0dd672a6
SM
147 (setq prefix-arg prefix)
148 ;; `setup-specified-language-environment', for instance,
149 ;; expects this to be set from a menu keymap.
150 (setq last-command-event (car (last event)))
151 ;; mouse-major-mode-menu was using `command-execute' instead.
65b61266 152 (call-interactively cmd))))
bcd010a0
DL
153
154(defvar mouse-major-mode-menu-prefix) ; dynamically bound
155
6a16c4cb 156(defun mouse-major-mode-menu (event prefix)
b98e5762
DL
157 "Pop up a mode-specific menu of mouse commands.
158Default to the Edit menu if the major mode doesn't define a menu."
95132d1c
RS
159 ;; Switch to the window clicked on, because otherwise
160 ;; the mode's commands may not make sense.
6a16c4cb 161 (interactive "@e\nP")
25f9b4bf 162 ;; Let the mode update its menus first.
179fc9ef 163 (run-hooks 'activate-menubar-hook 'menu-bar-update-hook)
b98e5762
DL
164 (let* (;; This is where mouse-major-mode-menu-prefix
165 ;; returns the prefix we should use (after menu-bar).
166 ;; It is either nil or (SOME-SYMBOL).
167 (mouse-major-mode-menu-prefix nil)
168 ;; Keymap from which to inherit; may be null.
169 (ancestor (mouse-major-mode-menu-1
170 (and (current-local-map)
25db2767 171 (local-key-binding [menu-bar]))))
b98e5762
DL
172 ;; Make a keymap in which our last command leads to a menu or
173 ;; default to the edit menu.
174 (newmap (if ancestor
175 (make-sparse-keymap (concat mode-name " Mode"))
176 menu-bar-edit-menu))
177 result)
178 (if ancestor
179 ;; Make our menu inherit from the desired keymap which we want
180 ;; to display as the menu now.
181 (set-keymap-parent newmap ancestor))
21ad0f7b
SM
182 (popup-menu newmap event prefix)))
183
95132d1c
RS
184
185;; Compute and cache the equivalent keys in MENU and all its submenus.
d5c847bb
KH
186;;;(defun mouse-major-mode-menu-compute-equiv-keys (menu)
187;;; (and (eq (car menu) 'keymap)
188;;; (x-popup-menu nil menu))
189;;; (while menu
190;;; (and (consp (car menu))
191;;; (consp (cdr (car menu)))
192;;; (let ((tail (cdr (car menu))))
193;;; (while (and (consp tail)
194;;; (not (eq (car tail) 'keymap)))
195;;; (setq tail (cdr tail)))
196;;; (if (consp tail)
197;;; (mouse-major-mode-menu-compute-equiv-keys tail))))
198;;; (setq menu (cdr menu))))
95132d1c
RS
199
200;; Given a mode's menu bar keymap,
201;; if it defines exactly one menu bar menu,
202;; return just that menu.
203;; Otherwise return a menu for all of them.
204(defun mouse-major-mode-menu-1 (menubar)
205 (if menubar
206 (let ((tail menubar)
207 submap)
208 (while tail
209 (if (consp (car tail))
210 (if submap
211 (setq submap t)
d5c847bb 212 (setq submap (car tail))))
95132d1c 213 (setq tail (cdr tail)))
d5c847bb 214 (if (eq submap t)
d3e458b0 215 menubar
d5c847bb 216 (setq mouse-major-mode-menu-prefix (list (car submap)))
a45423d8 217 (lookup-key menubar (vector (car submap)))))))
de420e82
DL
218
219(defun mouse-popup-menubar (event prefix)
a7df580d 220 "Pop up a menu equivalent to the menu bar for keyboard EVENT with PREFIX.
de420e82
DL
221The contents are the items that would be in the menu bar whether or
222not it is actually displayed."
223 (interactive "@e \nP")
179fc9ef 224 (run-hooks 'activate-menubar-hook 'menu-bar-update-hook)
7636d2a3
EZ
225 (let* ((local-menu (and (current-local-map)
226 (lookup-key (current-local-map) [menu-bar])))
227 (global-menu (lookup-key global-map [menu-bar]))
59836110
EZ
228 ;; If a keymap doesn't have a prompt string (a lazy
229 ;; programmer didn't bother to provide one), create it and
230 ;; insert it into the keymap; each keymap gets its own
231 ;; prompt. This is required for non-toolkit versions to
232 ;; display non-empty menu pane names.
233 (minor-mode-menus
234 (mapcar
235 (function
236 (lambda (menu)
237 (let* ((minor-mode (car menu))
238 (menu (cdr menu))
239 (title-or-map (cadr menu)))
240 (or (stringp title-or-map)
241 (setq menu
242 (cons 'keymap
243 (cons (concat
244 (capitalize (subst-char-in-string
245 ?- ?\ (symbol-name
246 minor-mode)))
247 " Menu")
248 (cdr menu)))))
249 menu)))
250 (minor-mode-key-binding [menu-bar])))
7636d2a3
EZ
251 (local-title-or-map (and local-menu (cadr local-menu)))
252 (global-title-or-map (cadr global-menu)))
7636d2a3
EZ
253 (or (null local-menu)
254 (stringp local-title-or-map)
255 (setq local-menu (cons 'keymap
256 (cons (concat mode-name " Mode Menu")
257 (cdr local-menu)))))
258 (or (stringp global-title-or-map)
259 (setq global-menu (cons 'keymap
260 (cons "Global Menu"
261 (cdr global-menu)))))
de420e82 262 ;; Supplying the list is faster than making a new map.
25db2767
DL
263 (popup-menu (append (list global-menu)
264 (if local-menu
265 (list local-menu))
266 minor-mode-menus)
7636d2a3 267 event prefix)))
de420e82
DL
268
269(defun mouse-popup-menubar-stuff (event prefix)
270 "Popup a menu like either `mouse-major-mode-menu' or `mouse-popup-menubar'.
271Use the former if the menu bar is showing, otherwise the latter."
272 (interactive "@e \nP")
273 (if (zerop (assoc-default 'menu-bar-lines (frame-parameters) 'eq 0))
274 (mouse-popup-menubar event prefix)
275 (mouse-major-mode-menu event prefix)))
95132d1c 276\f
544e7e73
RS
277;; Commands that operate on windows.
278
d65147f6
KH
279(defun mouse-minibuffer-check (event)
280 (let ((w (posn-window (event-start event))))
281 (and (window-minibuffer-p w)
282 (not (minibuffer-window-active-p w))
33c448cd
RS
283 (error "Minibuffer window is not active")))
284 ;; Give temporary modes such as isearch a chance to turn off.
285 (run-hooks 'mouse-leave-buffer-hook))
d65147f6 286
cc0a8174 287(defun mouse-delete-window (click)
947da0c4 288 "Delete the window you click on.
6b48d742 289Do nothing if the frame has just one window.
a926a0fa 290This command must be bound to a mouse click."
ec558adc 291 (interactive "e")
6b48d742 292 (unless (one-window-p t)
a926a0fa
RS
293 (mouse-minibuffer-check click)
294 (delete-window (posn-window (event-start click)))))
cc0a8174 295
3c2dd2c0
RS
296(defun mouse-select-window (click)
297 "Select the window clicked on; don't move point."
298 (interactive "e")
d65147f6 299 (mouse-minibuffer-check click)
3c2dd2c0
RS
300 (let ((oframe (selected-frame))
301 (frame (window-frame (posn-window (event-start click)))))
302 (select-window (posn-window (event-start click)))
303 (raise-frame frame)
304 (select-frame frame)
305 (or (eq frame oframe)
e1877477 306 (set-mouse-position (selected-frame) (1- (frame-width)) 0))))
3c2dd2c0 307
b0f3a26b
JB
308(defun mouse-tear-off-window (click)
309 "Delete the window clicked on, and create a new frame displaying its buffer."
310 (interactive "e")
d65147f6 311 (mouse-minibuffer-check click)
b0f3a26b
JB
312 (let* ((window (posn-window (event-start click)))
313 (buf (window-buffer window))
01a911e3 314 (frame (make-frame)))
b0f3a26b
JB
315 (select-frame frame)
316 (switch-to-buffer buf)
317 (delete-window window)))
318
b5370f03 319(defun mouse-delete-other-windows ()
5925bb84 320 "Delete all windows except the one you click on."
b5370f03 321 (interactive "@")
cc0a8174 322 (delete-other-windows))
72ea54a4 323
cc0a8174
JB
324(defun mouse-split-window-vertically (click)
325 "Select Emacs window mouse is on, then split it vertically in half.
326The window is split at the line clicked on.
327This command must be bound to a mouse click."
947da0c4 328 (interactive "@e")
d65147f6 329 (mouse-minibuffer-check click)
b5370f03
JB
330 (let ((start (event-start click)))
331 (select-window (posn-window start))
85d6b80b 332 (let ((new-height (1+ (cdr (posn-col-row (event-end click)))))
5ba2dc3f
JB
333 (first-line window-min-height)
334 (last-line (- (window-height) window-min-height)))
335 (if (< last-line first-line)
0a50b993 336 (error "Window too short to split")
5ba2dc3f
JB
337 (split-window-vertically
338 (min (max new-height first-line) last-line))))))
cc0a8174 339
947da0c4
RS
340(defun mouse-split-window-horizontally (click)
341 "Select Emacs window mouse is on, then split it horizontally in half.
342The window is split at the column clicked on.
343This command must be bound to a mouse click."
344 (interactive "@e")
d65147f6 345 (mouse-minibuffer-check click)
5ba2dc3f
JB
346 (let ((start (event-start click)))
347 (select-window (posn-window start))
348 (let ((new-width (1+ (car (posn-col-row (event-end click)))))
349 (first-col window-min-width)
350 (last-col (- (window-width) window-min-width)))
351 (if (< last-col first-col)
0a50b993 352 (error "Window too narrow to split")
5ba2dc3f
JB
353 (split-window-horizontally
354 (min (max new-width first-col) last-col))))))
947da0c4 355
4a4fa24d
RS
356(defun mouse-drag-window-above (window)
357 "Return the (or a) window directly above WINDOW.
358That means one whose bottom edge is at the same height as WINDOW's top edge."
359 (let ((top (nth 1 (window-edges window)))
360 (start-window window)
361 above-window)
362 (setq window (previous-window window 0))
363 (while (and (not above-window) (not (eq window start-window)))
364 (if (= (+ (window-height window) (nth 1 (window-edges window)))
365 top)
366 (setq above-window window))
367 (setq window (previous-window window)))
368 above-window))
369
370(defun mouse-drag-move-window-bottom (window growth)
371 "Move the bottom of WINDOW up or down by GROWTH lines.
372Move it down if GROWTH is positive, or up if GROWTH is negative.
373If this would make WINDOW too short,
374shrink the window or windows above it to make room."
375 (let ((excess (- window-min-height (+ (window-height window) growth))))
376 ;; EXCESS is the number of lines we need to take from windows above.
377 (if (> excess 0)
378 ;; This can recursively shrink windows all the way up.
379 (let ((window-above (mouse-drag-window-above window)))
380 (if window-above
381 (mouse-drag-move-window-bottom window-above (- excess))))))
382 (save-selected-window
383 (select-window window)
384 (enlarge-window growth nil (> growth 0))))
385
7a892a8b
DP
386(defsubst mouse-drag-move-window-top (window growth)
387 "Move the top of WINDOW up or down by GROWTH lines.
388Move it down if GROWTH is positive, or up if GROWTH is negative.
389If this would make WINDOW too short, shrink the window or windows
390above it to make room."
391 ;; Moving the top of WINDOW is actually moving the bottom of the
392 ;; window above.
393 (let ((window-above (mouse-drag-window-above window)))
394 (and window-above
395 (mouse-drag-move-window-bottom window-above (- growth)))))
396
b0d22e20
GM
397(defun mouse-drag-mode-line-1 (start-event mode-line-p)
398 "Change the height of a window by dragging on the mode or header line.
399START-EVENT is the starting mouse-event of the drag action.
4a4fa24d 400MODE-LINE-P non-nil means dragging a mode line; nil means a header line."
33c448cd
RS
401 ;; Give temporary modes such as isearch a chance to turn off.
402 (run-hooks 'mouse-leave-buffer-hook)
ee0e2bdd
GM
403 (let* ((done nil)
404 (echo-keystrokes 0)
405 (start (event-start start-event))
406 (start-event-window (posn-window start))
407 (start-event-frame (window-frame start-event-window))
408 (start-nwindows (count-windows t))
409 (old-selected-window (selected-window))
410 (minibuffer (frame-parameter nil 'minibuffer))
411 should-enlarge-minibuffer event mouse y top bot edges wconfig growth)
544e7e73
RS
412 (track-mouse
413 (progn
414 ;; enlarge-window only works on the selected window, so
415 ;; we must select the window where the start event originated.
416 ;; unwind-protect will restore the old selected window later.
417 (select-window start-event-window)
7b611de0 418
544e7e73
RS
419 ;; if this is the bottommost ordinary window, then to
420 ;; move its modeline the minibuffer must be enlarged.
421 (setq should-enlarge-minibuffer
422 (and minibuffer
b0d22e20 423 mode-line-p
544e7e73
RS
424 (not (one-window-p t))
425 (= (nth 1 (window-edges minibuffer))
426 (nth 3 (window-edges)))))
7b611de0 427
544e7e73
RS
428 ;; loop reading events and sampling the position of
429 ;; the mouse.
430 (while (not done)
431 (setq event (read-event)
432 mouse (mouse-position))
7b611de0 433
544e7e73
RS
434 ;; do nothing if
435 ;; - there is a switch-frame event.
436 ;; - the mouse isn't in the frame that we started in
437 ;; - the mouse isn't in any Emacs frame
438 ;; drag if
439 ;; - there is a mouse-movement event
440 ;; - there is a scroll-bar-movement event
441 ;; (same as mouse movement for our purposes)
442 ;; quit if
443 ;; - there is a keyboard event or some other unknown event
444 ;; unknown event.
445 (cond ((integerp event)
446 (setq done t))
7b611de0 447
fbd8dc8a 448 ((memq (car event) '(switch-frame select-window))
544e7e73 449 nil)
7b611de0 450
ee0e2bdd
GM
451 ((not (memq (car event) '(mouse-movement scroll-bar-movement)))
452 (when (consp event)
453 (push event unread-command-events))
544e7e73 454 (setq done t))
7b611de0 455
544e7e73
RS
456 ((not (eq (car mouse) start-event-frame))
457 nil)
7b611de0 458
544e7e73
RS
459 ((null (car (cdr mouse)))
460 nil)
7b611de0 461
544e7e73
RS
462 (t
463 (setq y (cdr (cdr mouse))
464 edges (window-edges)
465 top (nth 1 edges)
466 bot (nth 3 edges))
7b611de0 467
544e7e73 468 ;; compute size change needed
b0d22e20 469 (cond (mode-line-p
b0d22e20 470 (setq growth (- y bot -1)))
739e92a7
EZ
471 (t ; header line
472 (when (< (- bot y) window-min-height)
473 (setq y (- bot window-min-height)))
474 ;; The window's top includes the header line!
475 (setq growth (- top y))))
b0d22e20 476 (setq wconfig (current-window-configuration))
7b611de0 477
951e0427 478 ;; Check for an error case.
ee0e2bdd
GM
479 (when (and (/= growth 0)
480 (not minibuffer)
481 (one-window-p t))
482 (error "Attempt to resize sole window"))
7b611de0 483
544e7e73
RS
484 ;; grow/shrink minibuffer?
485 (if should-enlarge-minibuffer
486 (progn
487 ;; yes. briefly select minibuffer so
488 ;; enlarge-window will affect the
489 ;; correct window.
490 (select-window minibuffer)
491 ;; scale back shrinkage if it would
492 ;; make the minibuffer less than 1
493 ;; line tall.
494 (if (and (> growth 0)
495 (< (- (window-height minibuffer)
496 growth)
497 1))
498 (setq growth (1- (window-height minibuffer))))
499 (enlarge-window (- growth))
500 (select-window start-event-window))
501 ;; no. grow/shrink the selected window
ee0e2bdd 502 ;(message "growth = %d" growth)
7a892a8b
DP
503 (if mode-line-p
504 (mouse-drag-move-window-bottom start-event-window growth)
505 (mouse-drag-move-window-top start-event-window growth)))
7b611de0 506
544e7e73
RS
507 ;; if this window's growth caused another
508 ;; window to be deleted because it was too
509 ;; short, rescind the change.
510 ;;
511 ;; if size change caused space to be stolen
512 ;; from a window above this one, rescind the
a45423d8 513 ;; change, but only if we didn't grow/shrink
544e7e73
RS
514 ;; the minibuffer. minibuffer size changes
515 ;; can cause all windows to shrink... no way
516 ;; around it.
ee0e2bdd
GM
517 (when (or (/= start-nwindows (count-windows t))
518 (and (not should-enlarge-minibuffer)
4a4fa24d 519 (> growth 0)
ee0e2bdd
GM
520 mode-line-p
521 (/= top (nth 1 (window-edges)))))
522 (set-window-configuration wconfig)))))))))
b0d22e20
GM
523
524(defun mouse-drag-mode-line (start-event)
525 "Change the height of a window by dragging on the mode line."
526 (interactive "e")
527 (mouse-drag-mode-line-1 start-event t))
528
529(defun mouse-drag-header-line (start-event)
ee0e2bdd
GM
530 "Change the height of a window by dragging on the header line.
531Windows whose header-lines are at the top of the frame cannot be
532resized by dragging their header-line."
b0d22e20 533 (interactive "e")
ee0e2bdd
GM
534 ;; Changing the window's size by dragging its header-line when the
535 ;; header-line is at the top of the frame is somewhat strange,
536 ;; because the header-line doesn't move, so don't do it.
537 (let* ((start (event-start start-event))
538 (window (posn-window start))
539 (frame (window-frame window))
540 (first-window (frame-first-window frame)))
541 (when (or (eq window first-window)
542 (= (nth 1 (window-edges window))
543 (nth 1 (window-edges first-window))))
544 (error "Cannot move header-line at the top of the frame"))
545 (mouse-drag-mode-line-1 start-event nil)))
b0d22e20 546
544e7e73 547\f
08a1c178
RS
548(defun mouse-drag-vertical-line (start-event)
549 "Change the width of a window by dragging on the vertical line."
550 (interactive "e")
551 ;; Give temporary modes such as isearch a chance to turn off.
552 (run-hooks 'mouse-leave-buffer-hook)
5d6a85e0
RS
553 (let* ((done nil)
554 (echo-keystrokes 0)
555 (start-event-frame (window-frame (car (car (cdr start-event)))))
556 (start-event-window (car (car (cdr start-event))))
557 (start-nwindows (count-windows t))
558 (old-selected-window (selected-window))
559 event mouse x left right edges wconfig growth
560 (which-side
561 (or (cdr (assq 'vertical-scroll-bars (frame-parameters start-event-frame)))
562 'right)))
08a1c178
RS
563 (if (one-window-p t)
564 (error "Attempt to resize sole ordinary window"))
4e363e7e
KH
565 (if (eq which-side 'right)
566 (if (= (nth 2 (window-edges start-event-window))
567 (frame-width start-event-frame))
568 (error "Attempt to drag rightmost scrollbar"))
569 (if (= (nth 0 (window-edges start-event-window)) 0)
570 (error "Attempt to drag leftmost scrollbar")))
08a1c178
RS
571 (track-mouse
572 (progn
573 ;; enlarge-window only works on the selected window, so
574 ;; we must select the window where the start event originated.
575 ;; unwind-protect will restore the old selected window later.
576 (select-window start-event-window)
577 ;; loop reading events and sampling the position of
578 ;; the mouse.
579 (while (not done)
580 (setq event (read-event)
581 mouse (mouse-position))
582 ;; do nothing if
583 ;; - there is a switch-frame event.
584 ;; - the mouse isn't in the frame that we started in
585 ;; - the mouse isn't in any Emacs frame
586 ;; drag if
587 ;; - there is a mouse-movement event
588 ;; - there is a scroll-bar-movement event
589 ;; (same as mouse movement for our purposes)
590 ;; quit if
591 ;; - there is a keyboard event or some other unknown event
592 ;; unknown event.
593 (cond ((integerp event)
594 (setq done t))
fbd8dc8a 595 ((memq (car event) '(switch-frame select-window))
08a1c178
RS
596 nil)
597 ((not (memq (car event)
598 '(mouse-movement scroll-bar-movement)))
599 (if (consp event)
600 (setq unread-command-events
601 (cons event unread-command-events)))
602 (setq done t))
603 ((not (eq (car mouse) start-event-frame))
604 nil)
605 ((null (car (cdr mouse)))
606 nil)
607 (t
b0ea497f
KH
608 (save-selected-window
609 ;; If the scroll bar is on the window's left,
610 ;; adjust the window on the left.
4e363e7e
KH
611 (unless (eq which-side 'right)
612 (select-window (previous-window)))
b0ea497f 613 (setq x (- (car (cdr mouse))
4e363e7e 614 (if (eq which-side 'right) 0 2))
b0ea497f
KH
615 edges (window-edges)
616 left (nth 0 edges)
617 right (nth 2 edges))
618 ;; scale back a move that would make the
619 ;; window too thin.
620 (if (< (- x left -1) window-min-width)
621 (setq x (+ left window-min-width -1)))
622 ;; compute size change needed
623 (setq growth (- x right -1)
624 wconfig (current-window-configuration))
625 (enlarge-window growth t)
626 ;; if this window's growth caused another
627 ;; window to be deleted because it was too
628 ;; thin, rescind the change.
629 ;;
630 ;; if size change caused space to be stolen
631 ;; from a window to the left of this one,
632 ;; rescind the change.
633 (if (or (/= start-nwindows (count-windows t))
634 (/= left (nth 0 (window-edges))))
635 (set-window-configuration wconfig))))))))))
08a1c178 636\f
2a5fa27b 637(defun mouse-set-point (event)
cc0a8174 638 "Move point to the position clicked on with the mouse.
2a5fa27b 639This should be bound to a mouse click event type."
ec558adc 640 (interactive "e")
d65147f6 641 (mouse-minibuffer-check event)
2a5fa27b
RS
642 ;; Use event-end in case called from mouse-drag-region.
643 ;; If EVENT is a click, event-end and event-start give same value.
541a44d2 644 (posn-set-point (event-end event)))
cc0a8174 645
e6c2f5d4
RS
646(defvar mouse-last-region-beg nil)
647(defvar mouse-last-region-end nil)
648(defvar mouse-last-region-tick nil)
649
650(defun mouse-region-match ()
651 "Return non-nil if there's an active region that was set with the mouse."
652 (and (mark t) mark-active
653 (eq mouse-last-region-beg (region-beginning))
654 (eq mouse-last-region-end (region-end))
655 (eq mouse-last-region-tick (buffer-modified-tick))))
656
652ccd35 657(defun mouse-set-region (click)
e37de120 658 "Set the region to the text dragged over, and copy to kill ring.
2a5fa27b 659This should be bound to a mouse drag event."
652ccd35 660 (interactive "e")
d65147f6 661 (mouse-minibuffer-check click)
652ccd35
RS
662 (let ((posn (event-start click))
663 (end (event-end click)))
664 (select-window (posn-window posn))
665 (if (numberp (posn-point posn))
666 (goto-char (posn-point posn)))
fcfc3c63 667 ;; If mark is highlighted, no need to bounce the cursor.
33a35434
KH
668 ;; On X, we highlight while dragging, thus once again no need to bounce.
669 (or transient-mark-mode
b86b9918 670 (memq (framep (selected-frame)) '(x pc w32))
fcfc3c63 671 (sit-for 1))
652ccd35 672 (push-mark)
1cc8a3f4 673 (set-mark (point))
652ccd35 674 (if (numberp (posn-point end))
e37de120
RS
675 (goto-char (posn-point end)))
676 ;; Don't set this-command to kill-region, so that a following
677 ;; C-w will not double the text in the kill ring.
91a6bc10 678 ;; Ignore last-command so we don't append to a preceding kill.
b2dae92a
KS
679 (when mouse-drag-copy-region
680 (let (this-command last-command deactivate-mark)
681 (copy-region-as-kill (mark) (point))))
e6c2f5d4
RS
682 (mouse-set-region-1)))
683
684(defun mouse-set-region-1 ()
a5809dbd 685 ;; Set transient-mark-mode for a little while.
cc47c660
RS
686 (if (memq transient-mark-mode '(nil identity))
687 (setq transient-mark-mode 'only))
e6c2f5d4
RS
688 (setq mouse-last-region-beg (region-beginning))
689 (setq mouse-last-region-end (region-end))
690 (setq mouse-last-region-tick (buffer-modified-tick)))
652ccd35 691
3b558d41 692(defcustom mouse-scroll-delay 0.25
600c6e3a
JB
693 "*The pause between scroll steps caused by mouse drags, in seconds.
694If you drag the mouse beyond the edge of a window, Emacs scrolls the
695window to bring the text beyond that edge into view, with a delay of
696this many seconds between scroll steps. Scrolling stops when you move
697the mouse back into the window, or release the button.
698This variable's value may be non-integral.
3b558d41
RS
699Setting this to zero causes Emacs to scroll as fast as it can."
700 :type 'number
701 :group 'mouse)
600c6e3a 702
3b558d41 703(defcustom mouse-scroll-min-lines 1
a3d6bb97
RS
704 "*The minimum number of lines scrolled by dragging mouse out of window.
705Moving the mouse out the top or bottom edge of the window begins
706scrolling repeatedly. The number of lines scrolled per repetition
707is normally equal to the number of lines beyond the window edge that
708the mouse has moved. However, it always scrolls at least the number
3b558d41
RS
709of lines specified by this variable."
710 :type 'integer
711 :group 'mouse)
08a1c178 712
e919a622
RS
713(defun mouse-scroll-subr (window jump &optional overlay start)
714 "Scroll the window WINDOW, JUMP lines at a time, until new input arrives.
600c6e3a
JB
715If OVERLAY is an overlay, let it stretch from START to the far edge of
716the newly visible text.
717Upon exit, point is at the far edge of the newly visible text."
08a1c178
RS
718 (cond
719 ((and (> jump 0) (< jump mouse-scroll-min-lines))
720 (setq jump mouse-scroll-min-lines))
721 ((and (< jump 0) (< (- jump) mouse-scroll-min-lines))
722 (setq jump (- mouse-scroll-min-lines))))
4e399a53
RS
723 (let ((opoint (point)))
724 (while (progn
725 (goto-char (window-start window))
726 (if (not (zerop (vertical-motion jump window)))
727 (progn
728 (set-window-start window (point))
729 (if (natnump jump)
0320e66f
RS
730 (if (window-end window)
731 (progn
732 (goto-char (window-end window))
733 ;; window-end doesn't reflect the window's new
734 ;; start position until the next redisplay.
735 (vertical-motion (1- jump) window))
736 (vertical-motion (- (window-height window) 2)))
4e399a53
RS
737 (goto-char (window-start window)))
738 (if overlay
739 (move-overlay overlay start (point)))
740 ;; Now that we have scrolled WINDOW properly,
741 ;; put point back where it was for the redisplay
742 ;; so that we don't mess up the selected window.
743 (or (eq window (selected-window))
744 (goto-char opoint))
d2287ded 745 (sit-for mouse-scroll-delay)))))
4e399a53
RS
746 (or (eq window (selected-window))
747 (goto-char opoint))))
fcfc3c63 748
dc269e81 749;; Create an overlay and immediately delete it, to get "overlay in no buffer".
600c6e3a 750(defvar mouse-drag-overlay (make-overlay 1 1))
dc269e81 751(delete-overlay mouse-drag-overlay)
600c6e3a
JB
752(overlay-put mouse-drag-overlay 'face 'region)
753
dd524dbd 754(defvar mouse-selection-click-count 0)
eb6ff46f 755
c8c5bd24
RS
756(defvar mouse-selection-click-count-buffer nil)
757
600c6e3a 758(defun mouse-drag-region (start-event)
bcd5aef1 759 "Set the region to the text that the mouse is dragged over.
78210c95
RS
760Highlight the drag area as you move the mouse.
761This must be bound to a button-down mouse event.
d017deb2 762In Transient Mark mode, the highlighting remains as long as the mark
6454615c
RS
763remains active. Otherwise, it remains until the next input event.
764
765If the click is in the echo area, display the `*Messages*' buffer."
bcd5aef1 766 (interactive "e")
fbd8dc8a
SM
767 (let ((w (posn-window (event-start start-event))))
768 (if (and (window-minibuffer-p w)
769 (not (minibuffer-window-active-p w)))
6454615c 770 (save-excursion
2e36c3b0 771 ;; Swallow the up-event.
6454615c
RS
772 (read-event)
773 (set-buffer "*Messages*")
774 (goto-char (point-max))
775 (display-buffer (current-buffer)))
776 ;; Give temporary modes such as isearch a chance to turn off.
777 (run-hooks 'mouse-leave-buffer-hook)
778 (mouse-drag-region-1 start-event))))
779
65f76581
KS
780
781(defun mouse-on-link-p (pos)
782 "Return non-nil if POS is on a link in the current buffer.
b0ca1b8a
KS
783POS must be a buffer position in the current buffer or an mouse
784event location in the selected window, see `event-start'.
185a53bb
KS
785However, if `mouse-1-click-in-non-selected-windows' is non-nil,
786POS may be a mouse event location in any window.
65f76581
KS
787
788A clickable link is identified by one of the following methods:
789
b41a4019 790- If the character at POS has a non-nil `follow-link' text or
e5fb57e9 791overlay property, the value of that property determines what to do.
65f76581 792
b41a4019
KS
793- If there is a local key-binding or a keybinding at position POS
794for the `follow-link' event, the binding of that event determines
795what to do.
65f76581 796
b41a4019
KS
797The resulting value determine whether POS is inside a link:
798
799- If the value is `mouse-face', POS is inside a link if there
65f76581
KS
800is a non-nil `mouse-face' property at POS. Return t in this case.
801
b41a4019 802- If the value is a function, FUNC, POS is inside a link if
65f76581 803the call \(FUNC POS) returns non-nil. Return the return value
b0ca1b8a 804from that call. Arg is \(posn-point POS) if POS is a mouse event,
65f76581 805
b41a4019 806- Otherwise, return the value itself.
65f76581
KS
807
808The return value is interpreted as follows:
809
810- If it is a string, the mouse-1 event is translated into the
811first character of the string, i.e. the action of the mouse-1
812click is the local or global binding of that character.
813
814- If it is a vector, the mouse-1 event is translated into the
815first element of that vector, i.e. the action of the mouse-1
816click is the local or global binding of that event.
817
818- Otherwise, the mouse-1 event is translated into a mouse-2 event
819at the same position."
185a53bb
KS
820 (let ((w (and (consp pos) (posn-window pos))))
821 (if (consp pos)
822 (setq pos (and (or mouse-1-click-in-non-selected-windows
823 (eq (selected-window) w))
824 (posn-point pos))))
825 (when pos
826 (with-current-buffer (window-buffer w)
827 (let ((action
828 (or (get-char-property pos 'follow-link)
829 (save-excursion
830 (goto-char pos)
831 (key-binding [follow-link] nil t)))))
832 (cond
833 ((eq action 'mouse-face)
834 (and (get-char-property pos 'mouse-face) t))
835 ((functionp action)
836 (funcall action pos))
837 (t action)))))))
b0ca1b8a 838
5dbda518
KS
839(defun mouse-fixup-help-message (msg)
840 "Fix help message MSG for `mouse-1-click-follows-link'."
841 (let (mp pos)
842 (if (and mouse-1-click-follows-link
843 (stringp msg)
844 (save-match-data
845 (string-match "^mouse-2" msg))
846 (setq mp (mouse-pixel-position))
847 (consp (setq pos (cdr mp)))
848 (car pos) (>= (car pos) 0)
849 (cdr pos) (>= (cdr pos) 0)
850 (setq pos (posn-at-x-y (car pos) (cdr pos) (car mp)))
851 (windowp (posn-window pos)))
852 (with-current-buffer (window-buffer (posn-window pos))
853 (if (mouse-on-link-p pos)
854 (setq msg (concat
855 (cond
856 ((eq mouse-1-click-follows-link 'double) "double-")
857 ((and (integerp mouse-1-click-follows-link)
858 (< mouse-1-click-follows-link 0)) "Long ")
859 (t ""))
860 "mouse-1" (substring msg 7)))))))
861 msg)
65f76581 862
6454615c 863(defun mouse-drag-region-1 (start-event)
d65147f6 864 (mouse-minibuffer-check start-event)
4c9afcbe
RS
865 (let* ((echo-keystrokes 0)
866 (start-posn (event-start start-event))
600c6e3a
JB
867 (start-point (posn-point start-posn))
868 (start-window (posn-window start-posn))
02beb936 869 (start-window-start (window-start start-window))
b846d039 870 (start-frame (window-frame start-window))
1853aa6b 871 (start-hscroll (window-hscroll start-window))
600c6e3a 872 (bounds (window-edges start-window))
8413d0d2 873 (make-cursor-line-fully-visible nil)
600c6e3a
JB
874 (top (nth 1 bounds))
875 (bottom (if (window-minibuffer-p start-window)
876 (nth 3 bounds)
877 ;; Don't count the mode line.
e37de120 878 (1- (nth 3 bounds))))
b0ca1b8a 879 (on-link (and mouse-1-click-follows-link
185a53bb
KS
880 (or mouse-1-click-in-non-selected-windows
881 (eq start-window (selected-window)))))
b0ca1b8a 882 remap-double-click
e37de120 883 (click-count (1- (event-click-count start-event))))
eb6ff46f 884 (setq mouse-selection-click-count click-count)
c8c5bd24 885 (setq mouse-selection-click-count-buffer (current-buffer))
b80f1928 886 (mouse-set-point start-event)
08a1c178
RS
887 ;; In case the down click is in the middle of some intangible text,
888 ;; use the end of that text, and put it in START-POINT.
889 (if (< (point) start-point)
890 (goto-char start-point))
891 (setq start-point (point))
b0ca1b8a 892 (setq on-link (and on-link
65f76581
KS
893 (mouse-on-link-p start-point)))
894 (setq remap-double-click (and on-link
895 (eq mouse-1-click-follows-link 'double)
896 (= click-count 1)))
897 (if remap-double-click ;; Don't expand mouse overlay in links
898 (setq click-count 0))
e37de120
RS
899 (let ((range (mouse-start-end start-point start-point click-count)))
900 (move-overlay mouse-drag-overlay (car range) (nth 1 range)
2d246c71
RS
901 (window-buffer start-window))
902 (overlay-put mouse-drag-overlay 'window (selected-window)))
f767385c 903 (deactivate-mark)
08a1c178
RS
904 ;; end-of-range is used only in the single-click case.
905 ;; It is the place where the drag has reached so far
906 ;; (but not outside the window where the drag started).
d5c847bb 907 (let (event end end-point last-end-point (end-of-range (point)))
bcd5aef1 908 (track-mouse
600c6e3a 909 (while (progn
b846d039
JB
910 (setq event (read-event))
911 (or (mouse-movement-p event)
fbd8dc8a
SM
912 (memq (car-safe event) '(switch-frame select-window))))
913 (if (memq (car-safe event) '(switch-frame select-window))
b846d039
JB
914 nil
915 (setq end (event-end event)
916 end-point (posn-point end))
3617aa76 917 (if (numberp end-point)
d5c847bb 918 (setq last-end-point end-point))
b846d039
JB
919
920 (cond
b846d039
JB
921 ;; Are we moving within the original window?
922 ((and (eq (posn-window end) start-window)
923 (integer-or-marker-p end-point))
08a1c178
RS
924 ;; Go to START-POINT first, so that when we move to END-POINT,
925 ;; if it's in the middle of intangible text,
926 ;; point jumps in the direction away from START-POINT.
927 (goto-char start-point)
b846d039 928 (goto-char end-point)
08a1c178
RS
929 (if (zerop (% click-count 3))
930 (setq end-of-range (point)))
e37de120
RS
931 (let ((range (mouse-start-end start-point (point) click-count)))
932 (move-overlay mouse-drag-overlay (car range) (nth 1 range))))
b846d039 933
50e527bc
KH
934 (t
935 (let ((mouse-row (cdr (cdr (mouse-position)))))
b846d039 936 (cond
50e527bc 937 ((null mouse-row))
b846d039 938 ((< mouse-row top)
e919a622 939 (mouse-scroll-subr start-window (- mouse-row top)
f9278a75
RS
940 mouse-drag-overlay start-point)
941 ;; Without this, point tends to jump back to the starting
942 ;; position where the mouse button was pressed down.
943 (setq end-of-range (overlay-start mouse-drag-overlay)))
d2287ded 944 ((>= mouse-row bottom)
e919a622 945 (mouse-scroll-subr start-window (1+ (- mouse-row bottom))
ce8c2809 946 mouse-drag-overlay start-point)
f9278a75 947 (setq end-of-range (overlay-end mouse-drag-overlay))))))))))
b2013aad 948
2e3329a5
RS
949 ;; In case we did not get a mouse-motion event
950 ;; for the final move of the mouse before a drag event
951 ;; pretend that we did get one.
952 (when (and (memq 'drag (event-modifiers (car-safe event)))
953 (setq end (event-end event)
954 end-point (posn-point end))
955 (eq (posn-window end) start-window)
956 (integer-or-marker-p end-point))
2e3329a5
RS
957 ;; Go to START-POINT first, so that when we move to END-POINT,
958 ;; if it's in the middle of intangible text,
959 ;; point jumps in the direction away from START-POINT.
960 (goto-char start-point)
961 (goto-char end-point)
962 (if (zerop (% click-count 3))
963 (setq end-of-range (point)))
964 (let ((range (mouse-start-end start-point (point) click-count)))
965 (move-overlay mouse-drag-overlay (car range) (nth 1 range))))
966
4e399a53 967 (if (consp event)
e37de120 968 (let ((fun (key-binding (vector (car event)))))
bfbcf12e
RS
969 ;; Run the binding of the terminating up-event, if possible.
970 ;; In the case of a multiple click, it gives the wrong results,
971 ;; because it would fail to set up a region.
bb3aa835
RS
972 (if (not (= (overlay-start mouse-drag-overlay)
973 (overlay-end mouse-drag-overlay)))
974 (let* ((stop-point
975 (if (numberp (posn-point (event-end event)))
976 (posn-point (event-end event))
977 last-end-point))
978 ;; The end that comes from where we ended the drag.
979 ;; Point goes here.
980 (region-termination
981 (if (and stop-point (< stop-point start-point))
982 (overlay-start mouse-drag-overlay)
44dc5252 983 (overlay-end mouse-drag-overlay)))
bb3aa835
RS
984 ;; The end that comes from where we started the drag.
985 ;; Mark goes there.
986 (region-commencement
987 (- (+ (overlay-end mouse-drag-overlay)
988 (overlay-start mouse-drag-overlay))
989 region-termination))
990 last-command this-command)
991 (push-mark region-commencement t t)
992 (goto-char region-termination)
1fa01bcd 993 ;; Don't let copy-region-as-kill set deactivate-mark.
b2dae92a
KS
994 (when mouse-drag-copy-region
995 (let (deactivate-mark)
996 (copy-region-as-kill (point) (mark t))))
bb3aa835
RS
997 (let ((buffer (current-buffer)))
998 (mouse-show-mark)
999 ;; mouse-show-mark can call read-event,
1000 ;; and that means the Emacs server could switch buffers
7b611de0 1001 ;; under us. If that happened,
bb3aa835
RS
1002 ;; avoid trying to use the region.
1003 (and (mark t) mark-active
1004 (eq buffer (current-buffer))
1005 (mouse-set-region-1))))
1006 (delete-overlay mouse-drag-overlay)
1007 ;; Run the binding of the terminating up-event.
f45aab65 1008 (when (and (functionp fun)
02beb936
RS
1009 (= start-hscroll (window-hscroll start-window))
1010 ;; Don't run the up-event handler if the
1011 ;; window start changed in a redisplay after
1012 ;; the mouse-set-point for the down-mouse
1013 ;; event at the beginning of this function.
1014 ;; When the window start has changed, the
1015 ;; up-mouse event will contain a different
1016 ;; position due to the new window contents,
1017 ;; and point is set again.
1018 (or end-point
1019 (= (window-start start-window)
1020 start-window-start)))
65f76581 1021 (if (and on-link
5dbda518 1022 (or (not end-point) (= end-point start-point))
65f76581
KS
1023 (consp event)
1024 (or remap-double-click
1025 (and
1026 (not (eq mouse-1-click-follows-link 'double))
1027 (= click-count 0)
1028 (= (event-click-count event) 1)
1029 (not (input-pending-p))
1030 (or (not (integerp mouse-1-click-follows-link))
1031 (let ((t0 (posn-timestamp (event-start start-event)))
1032 (t1 (posn-timestamp (event-end event))))
1033 (and (integerp t0) (integerp t1)
1034 (if (> mouse-1-click-follows-link 0)
1035 (<= (- t1 t0) mouse-1-click-follows-link)
1036 (< (- t0 t1) mouse-1-click-follows-link)))))
1037 (or (not double-click-time)
1038 (sit-for 0 (if (integerp double-click-time)
1039 double-click-time 500) t)))))
1040 (if (or (vectorp on-link) (stringp on-link))
1041 (setq event (aref on-link 0))
1042 (setcar event 'mouse-2)))
1853aa6b
GM
1043 (setq unread-command-events
1044 (cons event unread-command-events)))))
e6c2f5d4 1045 (delete-overlay mouse-drag-overlay)))))
e37de120
RS
1046\f
1047;; Commands to handle xterm-style multiple clicks.
600c6e3a 1048
e37de120
RS
1049(defun mouse-skip-word (dir)
1050 "Skip over word, over whitespace, or over identical punctuation.
1051If DIR is positive skip forward; if negative, skip backward."
1052 (let* ((char (following-char))
1053 (syntax (char-to-string (char-syntax char))))
258e3295
KH
1054 (cond ((string= syntax "w")
1055 ;; Here, we can't use skip-syntax-forward/backward because
1056 ;; they don't pay attention to word-separating-categories,
1057 ;; and thus they will skip over a true word boundary. So,
1058 ;; we simularte the original behaviour by using
1059 ;; forward-word.
1060 (if (< dir 0)
1061 (if (not (looking-at "\\<"))
1062 (forward-word -1))
1063 (if (or (looking-at "\\<") (not (looking-at "\\>")))
1064 (forward-word 1))))
1065 ((string= syntax " ")
08a1c178
RS
1066 (if (< dir 0)
1067 (skip-syntax-backward syntax)
1068 (skip-syntax-forward syntax)))
1069 ((string= syntax "_")
1070 (if (< dir 0)
1071 (skip-syntax-backward "w_")
1072 (skip-syntax-forward "w_")))
1073 ((< dir 0)
1074 (while (and (not (bobp)) (= (preceding-char) char))
1075 (forward-char -1)))
1076 (t
1077 (while (and (not (eobp)) (= (following-char) char))
1078 (forward-char 1))))))
e37de120 1079
eb6ff46f 1080(defun mouse-start-end (start end mode)
a7df580d
DL
1081"Return a list of region bounds based on START and END according to MODE.
1082If MODE is 0 then set point to (min START END), mark to (max START END).
1083If MODE is 1 then set point to start of word at (min START END),
1084mark to end of word at (max START END).
1085If MODE is 2 then do the same for lines."
e37de120
RS
1086 (if (> start end)
1087 (let ((temp start))
1088 (setq start end
1089 end temp)))
9a974c88 1090 (setq mode (mod mode 3))
e37de120
RS
1091 (cond ((= mode 0)
1092 (list start end))
1093 ((and (= mode 1)
1094 (= start end)
1ec71583 1095 (char-after start)
e37de120 1096 (= (char-syntax (char-after start)) ?\())
6f482eec
RS
1097 (list start
1098 (save-excursion
1099 (goto-char start)
1100 (forward-sexp 1)
1101 (point))))
e37de120
RS
1102 ((and (= mode 1)
1103 (= start end)
1ec71583 1104 (char-after start)
e37de120 1105 (= (char-syntax (char-after start)) ?\)))
7b611de0 1106 (list (save-excursion
e37de120 1107 (goto-char (1+ start))
d89a4a47
RS
1108 (backward-sexp 1)
1109 (point))
e37de120 1110 (1+ start)))
53770877
RS
1111 ((and (= mode 1)
1112 (= start end)
1113 (char-after start)
1114 (= (char-syntax (char-after start)) ?\"))
1115 (let ((open (or (eq start (point-min))
1116 (save-excursion
1117 (goto-char (- start 1))
1118 (looking-at "\\s(\\|\\s \\|\\s>")))))
1119 (if open
1120 (list start
1121 (save-excursion
1122 (condition-case nil
7b611de0 1123 (progn
53770877
RS
1124 (goto-char start)
1125 (forward-sexp 1)
1126 (point))
1127 (error end))))
f1017d55 1128 (list (save-excursion
53770877
RS
1129 (condition-case nil
1130 (progn
1131 (goto-char (1+ start))
1132 (backward-sexp 1)
1133 (point))
f1017d55
RS
1134 (error end)))
1135 (1+ start)))))
e37de120
RS
1136 ((= mode 1)
1137 (list (save-excursion
1138 (goto-char start)
1139 (mouse-skip-word -1)
1140 (point))
1141 (save-excursion
1142 (goto-char end)
1143 (mouse-skip-word 1)
1144 (point))))
1145 ((= mode 2)
1146 (list (save-excursion
1147 (goto-char start)
1148 (beginning-of-line 1)
1149 (point))
1150 (save-excursion
1151 (goto-char end)
1152 (forward-line 1)
1153 (point))))))
e66feb07 1154\f
3f26b32a
RS
1155;; Subroutine: set the mark where CLICK happened,
1156;; but don't do anything else.
1157(defun mouse-set-mark-fast (click)
d65147f6 1158 (mouse-minibuffer-check click)
3f26b32a
RS
1159 (let ((posn (event-start click)))
1160 (select-window (posn-window posn))
1161 (if (numberp (posn-point posn))
1162 (push-mark (posn-point posn) t t))))
1163
98aac09d
MB
1164(defun mouse-undouble-last-event (events)
1165 (let* ((index (1- (length events)))
1166 (last (nthcdr index events))
1167 (event (car last))
1168 (basic (event-basic-type event))
397a88f3
RS
1169 (old-modifiers (event-modifiers event))
1170 (modifiers (delq 'double (delq 'triple (copy-sequence old-modifiers))))
98aac09d
MB
1171 (new
1172 (if (consp event)
7132500b
RS
1173 ;; Use reverse, not nreverse, since event-modifiers
1174 ;; does not copy the list it returns.
3bb846b8 1175 (cons (event-convert-list (reverse (cons basic modifiers)))
98aac09d
MB
1176 (cdr event))
1177 event)))
1178 (setcar last new)
397a88f3
RS
1179 (if (and (not (equal modifiers old-modifiers))
1180 (key-binding (apply 'vector events)))
98aac09d
MB
1181 t
1182 (setcar last event)
1183 nil)))
1184
7b611de0 1185;; Momentarily show where the mark is, if highlighting doesn't show it.
7aeb7370 1186
88f20a3d 1187(defvar mouse-region-delete-keys '([delete] [deletechar])
7aeb7370
RS
1188 "List of keys which shall cause the mouse region to be deleted.")
1189
3f26b32a 1190(defun mouse-show-mark ()
d3d3d650
RS
1191 (let ((inhibit-quit t)
1192 (echo-keystrokes 0)
1193 event events key ignore
b10c429f 1194 (x-lost-selection-functions
ab60bd74
SS
1195 (when (boundp 'x-lost-selection-functions)
1196 (copy-sequence x-lost-selection-functions))))
1197 (add-hook 'x-lost-selection-functions
d3d3d650 1198 (lambda (seltype)
ab60bd74
SS
1199 (when (eq seltype 'PRIMARY)
1200 (setq ignore t)
1201 (throw 'mouse-show-mark t))))
d3d3d650
RS
1202 (if transient-mark-mode
1203 (delete-overlay mouse-drag-overlay)
1204 (move-overlay mouse-drag-overlay (point) (mark t)))
1205 (catch 'mouse-show-mark
1206 ;; In this loop, execute scroll bar and switch-frame events.
fbd8dc8a 1207 ;; Should we similarly handle `select-window' events? --Stef
d3d3d650
RS
1208 ;; Also ignore down-events that are undefined.
1209 (while (progn (setq event (read-event))
1210 (setq events (append events (list event)))
1211 (setq key (apply 'vector events))
1212 (or (and (consp event)
1213 (eq (car event) 'switch-frame))
1214 (and (consp event)
1215 (eq (posn-point (event-end event))
1216 'vertical-scroll-bar))
1217 (and (memq 'down (event-modifiers event))
1218 (not (key-binding key))
1219 (not (mouse-undouble-last-event events))
1220 (not (member key mouse-region-delete-keys)))))
1221 (and (consp event)
1222 (or (eq (car event) 'switch-frame)
1223 (eq (posn-point (event-end event))
1224 'vertical-scroll-bar))
1225 (let ((keys (vector 'vertical-scroll-bar event)))
1226 (and (key-binding keys)
1227 (progn
1228 (call-interactively (key-binding keys)
1229 nil keys)
1230 (setq events nil)))))))
1231 ;; If we lost the selection, just turn off the highlighting.
ab60bd74 1232 (unless ignore
d3d3d650
RS
1233 ;; For certain special keys, delete the region.
1234 (if (member key mouse-region-delete-keys)
9e6856a7 1235 (delete-region (mark t) (point))
d3d3d650
RS
1236 ;; Otherwise, unread the key so it gets executed normally.
1237 (setq unread-command-events
1238 (nconc events unread-command-events))))
1239 (setq quit-flag nil)
1240 (unless transient-mark-mode
f4b60fe6 1241 (delete-overlay mouse-drag-overlay))))
3f26b32a 1242
cc0a8174
JB
1243(defun mouse-set-mark (click)
1244 "Set mark at the position clicked on with the mouse.
1245Display cursor at that position for a second.
1246This must be bound to a mouse click."
ec558adc 1247 (interactive "e")
f598fb03
RS
1248 (mouse-minibuffer-check click)
1249 (select-window (posn-window (event-start click)))
1250 ;; We don't use save-excursion because that preserves the mark too.
72ea54a4
RS
1251 (let ((point-save (point)))
1252 (unwind-protect
cc0a8174 1253 (progn (mouse-set-point click)
897897e3
RS
1254 (push-mark nil t t)
1255 (or transient-mark-mode
1256 (sit-for 1)))
72ea54a4
RS
1257 (goto-char point-save))))
1258
cc0a8174
JB
1259(defun mouse-kill (click)
1260 "Kill the region between point and the mouse click.
1261The text is saved in the kill ring, as with \\[kill-region]."
ec558adc 1262 (interactive "e")
d65147f6 1263 (mouse-minibuffer-check click)
142c7672
KH
1264 (let* ((posn (event-start click))
1265 (click-posn (posn-point posn)))
1266 (select-window (posn-window posn))
bd307392
JB
1267 (if (numberp click-posn)
1268 (kill-region (min (point) click-posn)
1269 (max (point) click-posn)))))
72ea54a4 1270
87ef29fd
JB
1271(defun mouse-yank-at-click (click arg)
1272 "Insert the last stretch of killed text at the position clicked on.
0e57ab65 1273Also move point to one end of the text thus inserted (normally the end),
231c4d1a 1274and set mark at the beginning.
50f58001
RS
1275Prefix arguments are interpreted as with \\[yank].
1276If `mouse-yank-at-point' is non-nil, insert at point
1277regardless of where you click."
a4cabe41 1278 (interactive "e\nP")
33c448cd
RS
1279 ;; Give temporary modes such as isearch a chance to turn off.
1280 (run-hooks 'mouse-leave-buffer-hook)
50f58001 1281 (or mouse-yank-at-point (mouse-set-point click))
d89a4a47 1282 (setq this-command 'yank)
a814e9df 1283 (setq mouse-selection-click-count 0)
87ef29fd
JB
1284 (yank arg))
1285
1286(defun mouse-kill-ring-save (click)
cc0a8174
JB
1287 "Copy the region between point and the mouse click in the kill ring.
1288This does not delete the region; it acts like \\[kill-ring-save]."
ec558adc 1289 (interactive "e")
3f26b32a 1290 (mouse-set-mark-fast click)
6452d8a6
RS
1291 (let (this-command last-command)
1292 (kill-ring-save (point) (mark t)))
3f26b32a 1293 (mouse-show-mark))
72ea54a4 1294
dbc4e1c1
JB
1295;;; This function used to delete the text between point and the mouse
1296;;; whenever it was equal to the front of the kill ring, but some
1297;;; people found that confusing.
1298
1299;;; A list (TEXT START END), describing the text and position of the last
1300;;; invocation of mouse-save-then-kill.
1301(defvar mouse-save-then-kill-posn nil)
1302
26d280b9 1303(defun mouse-save-then-kill-delete-region (beg end)
9a974c88
RS
1304 ;; We must make our own undo boundaries
1305 ;; because they happen automatically only for the current buffer.
1306 (undo-boundary)
dd524dbd
RS
1307 (if (or (= beg end) (eq buffer-undo-list t))
1308 ;; If we have no undo list in this buffer,
1309 ;; just delete.
1310 (delete-region beg end)
1311 ;; Delete, but make the undo-list entry share with the kill ring.
1312 ;; First, delete just one char, so in case buffer is being modified
1313 ;; for the first time, the undo list records that fact.
8faa9707 1314 (let (before-change-functions after-change-functions)
2f4b15ef
RS
1315 (delete-region beg
1316 (+ beg (if (> end beg) 1 -1))))
dd524dbd
RS
1317 (let ((buffer-undo-list buffer-undo-list))
1318 ;; Undo that deletion--but don't change the undo list!
8faa9707 1319 (let (before-change-functions after-change-functions)
2f4b15ef 1320 (primitive-undo 1 buffer-undo-list))
dd524dbd
RS
1321 ;; Now delete the rest of the specified region,
1322 ;; but don't record it.
1323 (setq buffer-undo-list t)
9a974c88
RS
1324 (if (/= (length (car kill-ring)) (- (max end beg) (min end beg)))
1325 (error "Lossage in mouse-save-then-kill-delete-region"))
dd524dbd
RS
1326 (delete-region beg end))
1327 (let ((tail buffer-undo-list))
1328 ;; Search back in buffer-undo-list for the string
1329 ;; that came from deleting one character.
1330 (while (and tail (not (stringp (car (car tail)))))
1331 (setq tail (cdr tail)))
1332 ;; Replace it with an entry for the entire deleted text.
1333 (and tail
9a974c88
RS
1334 (setcar tail (cons (car kill-ring) (min beg end))))))
1335 (undo-boundary))
eb6ff46f 1336
947da0c4 1337(defun mouse-save-then-kill (click)
40a45a9f
RS
1338 "Save text to point in kill ring; the second time, kill the text.
1339If the text between point and the mouse is the same as what's
1340at the front of the kill ring, this deletes the text.
1341Otherwise, it adds the text to the kill ring, like \\[kill-ring-save],
eb6ff46f
RS
1342which prepares for a second click to delete the text.
1343
1344If you have selected words or lines, this command extends the
1345selection through the word or line clicked on. If you do this
1346again in a different position, it extends the selection again.
7b611de0 1347If you do this twice in the same position, the selection is killed."
947da0c4 1348 (interactive "e")
53016bea
RS
1349 (let ((before-scroll
1350 (with-current-buffer (window-buffer (posn-window (event-start click)))
1351 point-before-scroll)))
b64548c7
RS
1352 (mouse-minibuffer-check click)
1353 (let ((click-posn (posn-point (event-start click)))
1354 ;; Don't let a subsequent kill command append to this one:
1355 ;; prevent setting this-command to kill-region.
1356 (this-command this-command))
c8c5bd24
RS
1357 (if (and (save-excursion
1358 (set-buffer (window-buffer (posn-window (event-start click))))
1359 (and (mark t) (> (mod mouse-selection-click-count 3) 0)
1360 ;; Don't be fooled by a recent click in some other buffer.
7b611de0 1361 (eq mouse-selection-click-count-buffer
c8c5bd24 1362 (current-buffer)))))
b64548c7
RS
1363 (if (not (and (eq last-command 'mouse-save-then-kill)
1364 (equal click-posn
1365 (car (cdr-safe (cdr-safe mouse-save-then-kill-posn))))))
1366 ;; Find both ends of the object selected by this click.
1367 (let* ((range
1368 (mouse-start-end click-posn click-posn
1369 mouse-selection-click-count)))
1370 ;; Move whichever end is closer to the click.
1371 ;; That's what xterm does, and it seems reasonable.
1372 (if (< (abs (- click-posn (mark t)))
1373 (abs (- click-posn (point))))
1374 (set-mark (car range))
1375 (goto-char (nth 1 range)))
1376 ;; We have already put the old region in the kill ring.
1377 ;; Replace it with the extended region.
1378 ;; (It would be annoying to make a separate entry.)
1379 (kill-new (buffer-substring (point) (mark t)) t)
e6c2f5d4 1380 (mouse-set-region-1)
b64548c7
RS
1381 ;; Arrange for a repeated mouse-3 to kill this region.
1382 (setq mouse-save-then-kill-posn
1383 (list (car kill-ring) (point) click-posn))
1384 (mouse-show-mark))
1385 ;; If we click this button again without moving it,
1386 ;; that time kill.
bcde3748 1387 (mouse-save-then-kill-delete-region (mark) (point))
b64548c7 1388 (setq mouse-selection-click-count 0)
dd524dbd 1389 (setq mouse-save-then-kill-posn nil))
b64548c7
RS
1390 (if (and (eq last-command 'mouse-save-then-kill)
1391 mouse-save-then-kill-posn
1392 (eq (car mouse-save-then-kill-posn) (car kill-ring))
1393 (equal (cdr mouse-save-then-kill-posn) (list (point) click-posn)))
1394 ;; If this is the second time we've called
1395 ;; mouse-save-then-kill, delete the text from the buffer.
1396 (progn
1397 (mouse-save-then-kill-delete-region (point) (mark))
1398 ;; After we kill, another click counts as "the first time".
1399 (setq mouse-save-then-kill-posn nil))
c8f264ae
RS
1400 ;; This is not a repetition.
1401 ;; We are adjusting an old selection or creating a new one.
b64548c7
RS
1402 (if (or (and (eq last-command 'mouse-save-then-kill)
1403 mouse-save-then-kill-posn)
1404 (and mark-active transient-mark-mode)
1405 (and (memq last-command
1406 '(mouse-drag-region mouse-set-region))
1407 (or mark-even-if-inactive
1408 (not transient-mark-mode))))
1409 ;; We have a selection or suitable region, so adjust it.
1410 (let* ((posn (event-start click))
1411 (new (posn-point posn)))
1412 (select-window (posn-window posn))
1413 (if (numberp new)
1414 (progn
1415 ;; Move whichever end of the region is closer to the click.
1416 ;; That is what xterm does, and it seems reasonable.
ed784c53 1417 (if (<= (abs (- new (point))) (abs (- new (mark t))))
b64548c7
RS
1418 (goto-char new)
1419 (set-mark new))
1420 (setq deactivate-mark nil)))
bcde3748
RS
1421 (kill-new (buffer-substring (point) (mark t)) t)
1422 (mouse-show-mark))
b64548c7
RS
1423 ;; Set the mark where point is, then move where clicked.
1424 (mouse-set-mark-fast click)
1425 (if before-scroll
1426 (goto-char before-scroll))
1427 (exchange-point-and-mark)
c8f264ae 1428 (kill-new (buffer-substring (point) (mark t)))
d0d57043 1429 (mouse-show-mark))
e6c2f5d4 1430 (mouse-set-region-1)
b64548c7
RS
1431 (setq mouse-save-then-kill-posn
1432 (list (car kill-ring) (point) click-posn)))))))
e66feb07
RS
1433\f
1434(global-set-key [M-mouse-1] 'mouse-start-secondary)
1435(global-set-key [M-drag-mouse-1] 'mouse-set-secondary)
1436(global-set-key [M-down-mouse-1] 'mouse-drag-secondary)
1437(global-set-key [M-mouse-3] 'mouse-secondary-save-then-kill)
9a974c88 1438(global-set-key [M-mouse-2] 'mouse-yank-secondary)
e66feb07
RS
1439
1440;; An overlay which records the current secondary selection
1441;; or else is deleted when there is no secondary selection.
1442;; May be nil.
1443(defvar mouse-secondary-overlay nil)
1444
a94c7fcc
RS
1445(defvar mouse-secondary-click-count 0)
1446
e66feb07
RS
1447;; A marker which records the specified first end for a secondary selection.
1448;; May be nil.
1449(defvar mouse-secondary-start nil)
1450
1451(defun mouse-start-secondary (click)
1452 "Set one end of the secondary selection to the position clicked on.
1453Use \\[mouse-secondary-save-then-kill] to set the other end
1454and complete the secondary selection."
1455 (interactive "e")
d65147f6 1456 (mouse-minibuffer-check click)
e66feb07 1457 (let ((posn (event-start click)))
230aaa73
RS
1458 (save-excursion
1459 (set-buffer (window-buffer (posn-window posn)))
1460 ;; Cancel any preexisting secondary selection.
1461 (if mouse-secondary-overlay
1462 (delete-overlay mouse-secondary-overlay))
1463 (if (numberp (posn-point posn))
1464 (progn
1465 (or mouse-secondary-start
1466 (setq mouse-secondary-start (make-marker)))
1467 (move-marker mouse-secondary-start (posn-point posn)))))))
e66feb07
RS
1468
1469(defun mouse-set-secondary (click)
1470 "Set the secondary selection to the text that the mouse is dragged over.
1471This must be bound to a mouse drag event."
1472 (interactive "e")
d65147f6 1473 (mouse-minibuffer-check click)
e66feb07
RS
1474 (let ((posn (event-start click))
1475 beg
1476 (end (event-end click)))
230aaa73
RS
1477 (save-excursion
1478 (set-buffer (window-buffer (posn-window posn)))
1479 (if (numberp (posn-point posn))
1480 (setq beg (posn-point posn)))
1481 (if mouse-secondary-overlay
1482 (move-overlay mouse-secondary-overlay beg (posn-point end))
1483 (setq mouse-secondary-overlay (make-overlay beg (posn-point end))))
1484 (overlay-put mouse-secondary-overlay 'face 'secondary-selection))))
947da0c4 1485
d89a4a47 1486(defun mouse-drag-secondary (start-event)
e66feb07 1487 "Set the secondary selection to the text that the mouse is dragged over.
d89a4a47 1488Highlight the drag area as you move the mouse.
efc10c97
RS
1489This must be bound to a button-down mouse event.
1490The function returns a non-nil value if it creates a secondary selection."
e66feb07 1491 (interactive "e")
d65147f6 1492 (mouse-minibuffer-check start-event)
4c9afcbe
RS
1493 (let* ((echo-keystrokes 0)
1494 (start-posn (event-start start-event))
d89a4a47
RS
1495 (start-point (posn-point start-posn))
1496 (start-window (posn-window start-posn))
1497 (start-frame (window-frame start-window))
1498 (bounds (window-edges start-window))
1499 (top (nth 1 bounds))
1500 (bottom (if (window-minibuffer-p start-window)
1501 (nth 3 bounds)
1502 ;; Don't count the mode line.
1503 (1- (nth 3 bounds))))
1504 (click-count (1- (event-click-count start-event))))
1505 (save-excursion
1506 (set-buffer (window-buffer start-window))
a94c7fcc 1507 (setq mouse-secondary-click-count click-count)
d89a4a47
RS
1508 (or mouse-secondary-overlay
1509 (setq mouse-secondary-overlay
1510 (make-overlay (point) (point))))
26d280b9 1511 (overlay-put mouse-secondary-overlay 'face 'secondary-selection)
9a974c88 1512 (if (> (mod click-count 3) 0)
26d280b9
RS
1513 ;; Double or triple press: make an initial selection
1514 ;; of one word or line.
d89a4a47
RS
1515 (let ((range (mouse-start-end start-point start-point click-count)))
1516 (set-marker mouse-secondary-start nil)
1517 (move-overlay mouse-secondary-overlay 1 1
1518 (window-buffer start-window))
1519 (move-overlay mouse-secondary-overlay (car range) (nth 1 range)
1520 (window-buffer start-window)))
26d280b9 1521 ;; Single-press: cancel any preexisting secondary selection.
d89a4a47
RS
1522 (or mouse-secondary-start
1523 (setq mouse-secondary-start (make-marker)))
1524 (set-marker mouse-secondary-start start-point)
1525 (delete-overlay mouse-secondary-overlay))
1526 (let (event end end-point)
1527 (track-mouse
1528 (while (progn
1529 (setq event (read-event))
1530 (or (mouse-movement-p event)
fbd8dc8a 1531 (memq (car-safe event) '(switch-frame select-window))))
d89a4a47 1532
fbd8dc8a 1533 (if (memq (car-safe event) '(switch-frame select-window))
d89a4a47
RS
1534 nil
1535 (setq end (event-end event)
1536 end-point (posn-point end))
1537 (cond
d89a4a47
RS
1538 ;; Are we moving within the original window?
1539 ((and (eq (posn-window end) start-window)
1540 (integer-or-marker-p end-point))
d89a4a47
RS
1541 (let ((range (mouse-start-end start-point end-point
1542 click-count)))
0136e1e3
RS
1543 (if (or (/= start-point end-point)
1544 (null (marker-position mouse-secondary-start)))
1545 (progn
1546 (set-marker mouse-secondary-start nil)
1547 (move-overlay mouse-secondary-overlay
1548 (car range) (nth 1 range))))))
3b0aebe9
RS
1549 (t
1550 (let ((mouse-row (cdr (cdr (mouse-position)))))
1551 (cond
1552 ((null mouse-row))
1553 ((< mouse-row top)
e919a622
RS
1554 (mouse-scroll-subr start-window (- mouse-row top)
1555 mouse-secondary-overlay start-point))
d2287ded 1556 ((>= mouse-row bottom)
e919a622 1557 (mouse-scroll-subr start-window (1+ (- mouse-row bottom))
3b0aebe9 1558 mouse-secondary-overlay start-point)))))))))
d89a4a47 1559
4e399a53 1560 (if (consp event)
d89a4a47
RS
1561 (if (marker-position mouse-secondary-start)
1562 (save-window-excursion
1563 (delete-overlay mouse-secondary-overlay)
9a974c88 1564 (x-set-selection 'SECONDARY nil)
d89a4a47
RS
1565 (select-window start-window)
1566 (save-excursion
1567 (goto-char mouse-secondary-start)
efc10c97
RS
1568 (sit-for 1)
1569 nil))
9a974c88
RS
1570 (x-set-selection
1571 'SECONDARY
1572 (buffer-substring (overlay-start mouse-secondary-overlay)
1573 (overlay-end mouse-secondary-overlay)))))))))
e66feb07 1574
9a974c88 1575(defun mouse-yank-secondary (click)
50f58001
RS
1576 "Insert the secondary selection at the position clicked on.
1577Move point to the end of the inserted text.
1578If `mouse-yank-at-point' is non-nil, insert at point
1579regardless of where you click."
a4cabe41 1580 (interactive "e")
33c448cd
RS
1581 ;; Give temporary modes such as isearch a chance to turn off.
1582 (run-hooks 'mouse-leave-buffer-hook)
50f58001
RS
1583 (or mouse-yank-at-point (mouse-set-point click))
1584 (insert (x-get-selection 'SECONDARY)))
9a974c88 1585
7e6404f6 1586(defun mouse-kill-secondary ()
9a974c88
RS
1587 "Kill the text in the secondary selection.
1588This is intended more as a keyboard command than as a mouse command
1589but it can work as either one.
1590
1591The current buffer (in case of keyboard use), or the buffer clicked on,
1592must be the one that the secondary selection is in. This requirement
1593is to prevent accidents."
7e6404f6
RS
1594 (interactive)
1595 (let* ((keys (this-command-keys))
1596 (click (elt keys (1- (length keys)))))
1597 (or (eq (overlay-buffer mouse-secondary-overlay)
1598 (if (listp click)
1599 (window-buffer (posn-window (event-start click)))
1600 (current-buffer)))
1601 (error "Select or click on the buffer where the secondary selection is")))
9dfab550
RS
1602 (let (this-command)
1603 (save-excursion
1604 (set-buffer (overlay-buffer mouse-secondary-overlay))
1605 (kill-region (overlay-start mouse-secondary-overlay)
1606 (overlay-end mouse-secondary-overlay))))
e66feb07 1607 (delete-overlay mouse-secondary-overlay)
9dfab550 1608;;; (x-set-selection 'SECONDARY nil)
e66feb07
RS
1609 (setq mouse-secondary-overlay nil))
1610
1611(defun mouse-secondary-save-then-kill (click)
d89a4a47 1612 "Save text to point in kill ring; the second time, kill the text.
7bbe2cc7
RS
1613You must use this in a buffer where you have recently done \\[mouse-start-secondary].
1614If the text between where you did \\[mouse-start-secondary] and where
1615you use this command matches the text at the front of the kill ring,
1616this command deletes the text.
e66feb07 1617Otherwise, it adds the text to the kill ring, like \\[kill-ring-save],
7bbe2cc7 1618which prepares for a second click with this command to delete the text.
d89a4a47 1619
7bbe2cc7
RS
1620If you have already made a secondary selection in that buffer,
1621this command extends or retracts the selection to where you click.
1622If you do this again in a different position, it extends or retracts
1623again. If you do this twice in the same position, it kills the selection."
e66feb07 1624 (interactive "e")
d65147f6 1625 (mouse-minibuffer-check click)
d89a4a47
RS
1626 (let ((posn (event-start click))
1627 (click-posn (posn-point (event-start click)))
e66feb07
RS
1628 ;; Don't let a subsequent kill command append to this one:
1629 ;; prevent setting this-command to kill-region.
1630 (this-command this-command))
9a974c88
RS
1631 (or (eq (window-buffer (posn-window posn))
1632 (or (and mouse-secondary-overlay
1633 (overlay-buffer mouse-secondary-overlay))
1634 (if mouse-secondary-start
1635 (marker-buffer mouse-secondary-start))))
1636 (error "Wrong buffer"))
1637 (save-excursion
1638 (set-buffer (window-buffer (posn-window posn)))
a94c7fcc 1639 (if (> (mod mouse-secondary-click-count 3) 0)
9a974c88
RS
1640 (if (not (and (eq last-command 'mouse-secondary-save-then-kill)
1641 (equal click-posn
1642 (car (cdr-safe (cdr-safe mouse-save-then-kill-posn))))))
1643 ;; Find both ends of the object selected by this click.
1644 (let* ((range
1645 (mouse-start-end click-posn click-posn
a94c7fcc 1646 mouse-secondary-click-count)))
9a974c88
RS
1647 ;; Move whichever end is closer to the click.
1648 ;; That's what xterm does, and it seems reasonable.
1649 (if (< (abs (- click-posn (overlay-start mouse-secondary-overlay)))
1650 (abs (- click-posn (overlay-end mouse-secondary-overlay))))
1651 (move-overlay mouse-secondary-overlay (car range)
1652 (overlay-end mouse-secondary-overlay))
d89a4a47
RS
1653 (move-overlay mouse-secondary-overlay
1654 (overlay-start mouse-secondary-overlay)
1655 (nth 1 range)))
9a974c88
RS
1656 ;; We have already put the old region in the kill ring.
1657 ;; Replace it with the extended region.
1658 ;; (It would be annoying to make a separate entry.)
f69140fd
KH
1659 (kill-new (buffer-substring
1660 (overlay-start mouse-secondary-overlay)
1661 (overlay-end mouse-secondary-overlay)) t)
9a974c88
RS
1662 ;; Arrange for a repeated mouse-3 to kill this region.
1663 (setq mouse-save-then-kill-posn
1664 (list (car kill-ring) (point) click-posn)))
1665 ;; If we click this button again without moving it,
1666 ;; that time kill.
d89a4a47 1667 (progn
9a974c88
RS
1668 (mouse-save-then-kill-delete-region
1669 (overlay-start mouse-secondary-overlay)
1670 (overlay-end mouse-secondary-overlay))
1671 (setq mouse-save-then-kill-posn nil)
a94c7fcc 1672 (setq mouse-secondary-click-count 0)
9a974c88
RS
1673 (delete-overlay mouse-secondary-overlay)))
1674 (if (and (eq last-command 'mouse-secondary-save-then-kill)
1675 mouse-save-then-kill-posn
1676 (eq (car mouse-save-then-kill-posn) (car kill-ring))
1677 (equal (cdr mouse-save-then-kill-posn) (list (point) click-posn)))
1678 ;; If this is the second time we've called
1679 ;; mouse-secondary-save-then-kill, delete the text from the buffer.
1680 (progn
1681 (mouse-save-then-kill-delete-region
1682 (overlay-start mouse-secondary-overlay)
1683 (overlay-end mouse-secondary-overlay))
1684 (setq mouse-save-then-kill-posn nil)
1685 (delete-overlay mouse-secondary-overlay))
1686 (if (overlay-start mouse-secondary-overlay)
1687 ;; We have a selection, so adjust it.
1688 (progn
1689 (if (numberp click-posn)
1690 (progn
1691 ;; Move whichever end of the region is closer to the click.
1692 ;; That is what xterm does, and it seems reasonable.
1693 (if (< (abs (- click-posn (overlay-start mouse-secondary-overlay)))
1694 (abs (- click-posn (overlay-end mouse-secondary-overlay))))
1695 (move-overlay mouse-secondary-overlay click-posn
1696 (overlay-end mouse-secondary-overlay))
d89a4a47
RS
1697 (move-overlay mouse-secondary-overlay
1698 (overlay-start mouse-secondary-overlay)
1699 click-posn))
9a974c88 1700 (setq deactivate-mark nil)))
0136e1e3 1701 (if (eq last-command 'mouse-secondary-save-then-kill)
7b611de0 1702 ;; If the front of the kill ring comes from
f69140fd
KH
1703 ;; an immediately previous use of this command,
1704 ;; replace it with the extended region.
1705 ;; (It would be annoying to make a separate entry.)
1706 (kill-new (buffer-substring
0136e1e3 1707 (overlay-start mouse-secondary-overlay)
f69140fd 1708 (overlay-end mouse-secondary-overlay)) t)
1fa01bcd
RS
1709 (let (deactivate-mark)
1710 (copy-region-as-kill (overlay-start mouse-secondary-overlay)
1711 (overlay-end mouse-secondary-overlay)))))
9a974c88
RS
1712 (if mouse-secondary-start
1713 ;; All we have is one end of a selection,
1714 ;; so put the other end here.
1715 (let ((start (+ 0 mouse-secondary-start)))
1716 (kill-ring-save start click-posn)
1717 (if mouse-secondary-overlay
1718 (move-overlay mouse-secondary-overlay start click-posn)
1719 (setq mouse-secondary-overlay (make-overlay start click-posn)))
1720 (overlay-put mouse-secondary-overlay 'face 'secondary-selection))))
1721 (setq mouse-save-then-kill-posn
1722 (list (car kill-ring) (point) click-posn))))
fb28fd5b
RS
1723 (if (overlay-buffer mouse-secondary-overlay)
1724 (x-set-selection 'SECONDARY
9a974c88
RS
1725 (buffer-substring
1726 (overlay-start mouse-secondary-overlay)
1727 (overlay-end mouse-secondary-overlay)))))))
e66feb07 1728\f
0d9be91c 1729(defcustom mouse-buffer-menu-maxlen 20
f1107960
RS
1730 "*Number of buffers in one pane (submenu) of the buffer menu.
1731If we have lots of buffers, divide them into groups of
0d9be91c 1732`mouse-buffer-menu-maxlen' and make a pane (or submenu) for each one."
3b558d41
RS
1733 :type 'integer
1734 :group 'mouse)
f1107960 1735
3ca87c7b
RS
1736(defcustom mouse-buffer-menu-mode-mult 4
1737 "*Group the buffers by the major mode groups on \\[mouse-buffer-menu]?
1738This number which determines (in a hairy way) whether \\[mouse-buffer-menu]
1739will split the buffer menu by the major modes (see
1740`mouse-buffer-menu-mode-groups') or just by menu length.
1741Set to 1 (or even 0!) if you want to group by major mode always, and to
1742a large number if you prefer a mixed multitude. The default is 4."
1743 :type 'integer
1744 :group 'mouse
1745 :version "20.3")
1746
284a88a3
RS
1747(defvar mouse-buffer-menu-mode-groups
1748 '(("Info\\|Help\\|Apropos\\|Man" . "Help")
1749 ("\\bVM\\b\\|\\bMH\\b\\|Message\\|Mail\\|Group\\|Score\\|Summary\\|Article"
1750 . "Mail/News")
1751 ("\\<C\\>" . "C")
1752 ("ObjC" . "C")
1753 ("Text" . "Text")
1754 ("Outline" . "Text")
c71a58a3
SS
1755 ("\\(HT\\|SG\\|X\\|XHT\\)ML" . "SGML")
1756 ("log\\|diff\\|vc\\|cvs" . "Version Control") ; "Change Management"?
284a88a3
RS
1757 ("Lisp" . "Lisp"))
1758 "How to group various major modes together in \\[mouse-buffer-menu].
1759Each element has the form (REGEXP . GROUPNAME).
1760If the major mode's name string matches REGEXP, use GROUPNAME instead.")
1761
8b34e79d 1762(defun mouse-buffer-menu (event)
2d82f7b9
RS
1763 "Pop up a menu of buffers for selection with the mouse.
1764This switches buffers in the window that you clicked on,
1765and selects that window."
ec558adc 1766 (interactive "e")
d65147f6 1767 (mouse-minibuffer-check event)
3ca87c7b 1768 (let ((buffers (buffer-list)) alist menu split-by-major-mode sum-of-squares)
284a88a3
RS
1769 ;; Make an alist of elements that look like (MENU-ITEM . BUFFER).
1770 (let ((tail buffers))
1771 (while tail
1772 ;; Divide all buffers into buckets for various major modes.
1773 ;; Each bucket looks like (MODE NAMESTRING BUFFERS...).
1774 (with-current-buffer (car tail)
1775 (let* ((adjusted-major-mode major-mode) elt)
1776 (let ((tail mouse-buffer-menu-mode-groups))
1777 (while tail
1778 (if (string-match (car (car tail)) mode-name)
1779 (setq adjusted-major-mode (cdr (car tail))))
1780 (setq tail (cdr tail))))
1781 (setq elt (assoc adjusted-major-mode split-by-major-mode))
1782 (if (null elt)
1783 (setq elt (list adjusted-major-mode
1784 (if (stringp adjusted-major-mode)
1785 adjusted-major-mode
1786 mode-name))
1787 split-by-major-mode (cons elt split-by-major-mode)))
1788 (or (memq (car tail) (cdr (cdr elt)))
1789 (setcdr (cdr elt) (cons (car tail) (cdr (cdr elt)))))))
1790 (setq tail (cdr tail))))
1791 ;; Compute the sum of squares of sizes of the major-mode buckets.
1792 (let ((tail split-by-major-mode))
1793 (setq sum-of-squares 0)
1794 (while tail
1795 (setq sum-of-squares
1796 (+ sum-of-squares
3ca87c7b 1797 (let ((len (length (cdr (cdr (car tail)))))) (* len len))))
284a88a3 1798 (setq tail (cdr tail))))
3ca87c7b
RS
1799 (if (< (* sum-of-squares mouse-buffer-menu-mode-mult)
1800 (* (length buffers) (length buffers)))
284a88a3
RS
1801 ;; Subdividing by major modes really helps, so let's do it.
1802 (let (subdivided-menus (buffers-left (length buffers)))
1803 ;; Sort the list to put the most popular major modes first.
1804 (setq split-by-major-mode
1805 (sort split-by-major-mode
1806 (function (lambda (elt1 elt2)
1807 (> (length elt1) (length elt2))))))
1808 ;; Make a separate submenu for each major mode
1809 ;; that has more than one buffer,
1810 ;; unless all the remaining buffers are less than 1/10 of them.
1811 (while (and split-by-major-mode
1812 (and (> (length (car split-by-major-mode)) 3)
1813 (> (* buffers-left 10) (length buffers))))
4b4ea1dc
EZ
1814 (let ((this-mode-list (mouse-buffer-menu-alist
1815 (cdr (cdr (car split-by-major-mode))))))
1816 (and this-mode-list
1817 (setq subdivided-menus
1818 (cons (cons
1819 (nth 1 (car split-by-major-mode))
1820 this-mode-list)
1821 subdivided-menus))))
284a88a3
RS
1822 (setq buffers-left
1823 (- buffers-left (length (cdr (car split-by-major-mode)))))
1824 (setq split-by-major-mode (cdr split-by-major-mode)))
1825 ;; If any major modes are left over,
1826 ;; make a single submenu for them.
1827 (if split-by-major-mode
4b4ea1dc
EZ
1828 (let ((others-list
1829 (mouse-buffer-menu-alist
1830 ;; we don't need split-by-major-mode any more,
1831 ;; so we can ditch it with nconc.
1832 (apply 'nconc (mapcar 'cddr split-by-major-mode)))))
1833 (and others-list
1834 (setq subdivided-menus
1835 (cons (cons "Others" others-list)
1836 subdivided-menus)))))
3ca87c7b 1837 (setq menu (cons "Buffer Menu" (nreverse subdivided-menus))))
284a88a3
RS
1838 (progn
1839 (setq alist (mouse-buffer-menu-alist buffers))
1840 (setq menu (cons "Buffer Menu"
1841 (mouse-buffer-menu-split "Select Buffer" alist)))))
2d82f7b9
RS
1842 (let ((buf (x-popup-menu event menu))
1843 (window (posn-window (event-start event))))
3ca87c7b 1844 (when buf
f134ad18
RS
1845 (select-window
1846 (if (framep window) (frame-selected-window window)
1847 window))
3ca87c7b 1848 (switch-to-buffer buf)))))
284a88a3
RS
1849
1850(defun mouse-buffer-menu-alist (buffers)
1851 (let (tail
1852 (maxlen 0)
1853 head)
1854 (setq buffers
1855 (sort buffers
1856 (function (lambda (elt1 elt2)
1857 (string< (buffer-name elt1) (buffer-name elt2))))))
1858 (setq tail buffers)
1859 (while tail
1860 (or (eq ?\ (aref (buffer-name (car tail)) 0))
1861 (setq maxlen
1862 (max maxlen
1863 (length (buffer-name (car tail))))))
1864 (setq tail (cdr tail)))
1865 (setq tail buffers)
1866 (while tail
1867 (let ((elt (car tail)))
1868 (if (/= (aref (buffer-name elt) 0) ?\ )
1869 (setq head
1870 (cons
1871 (cons
1872 (format
1873 (format "%%%ds %%s%%s %%s" maxlen)
1874 (buffer-name elt)
1875 (if (buffer-modified-p elt) "*" " ")
1876 (save-excursion
1877 (set-buffer elt)
1878 (if buffer-read-only "%" " "))
7b611de0 1879 (or (buffer-file-name elt)
284a88a3
RS
1880 (save-excursion
1881 (set-buffer elt)
1882 (if list-buffers-directory
1883 (expand-file-name
1884 list-buffers-directory)))
1885 ""))
1886 elt)
1887 head))))
1888 (setq tail (cdr tail)))
1889 ;; Compensate for the reversal that the above loop does.
1890 (nreverse head)))
1891
1892(defun mouse-buffer-menu-split (title alist)
1893 ;; If we have lots of buffers, divide them into groups of 20
1894 ;; and make a pane (or submenu) for each one.
0d9be91c 1895 (if (> (length alist) (/ (* mouse-buffer-menu-maxlen 3) 2))
284a88a3
RS
1896 (let ((alist alist) sublists next
1897 (i 1))
1898 (while alist
0d9be91c 1899 ;; Pull off the next mouse-buffer-menu-maxlen buffers
284a88a3 1900 ;; and make them the next element of sublist.
0d9be91c 1901 (setq next (nthcdr mouse-buffer-menu-maxlen alist))
284a88a3 1902 (if next
0d9be91c 1903 (setcdr (nthcdr (1- mouse-buffer-menu-maxlen) alist)
284a88a3
RS
1904 nil))
1905 (setq sublists (cons (cons (format "Buffers %d" i) alist)
1906 sublists))
1907 (setq i (1+ i))
1908 (setq alist next))
1909 (nreverse sublists))
1910 ;; Few buffers--put them all in one pane.
1911 (list (cons title alist))))
72ea54a4 1912\f
5ba2dc3f 1913;;; These need to be rewritten for the new scroll bar implementation.
dbc4e1c1
JB
1914
1915;;;!! ;; Commands for the scroll bar.
7b611de0 1916;;;!!
dbc4e1c1
JB
1917;;;!! (defun mouse-scroll-down (click)
1918;;;!! (interactive "@e")
1919;;;!! (scroll-down (1+ (cdr (mouse-coords click)))))
7b611de0 1920;;;!!
dbc4e1c1
JB
1921;;;!! (defun mouse-scroll-up (click)
1922;;;!! (interactive "@e")
1923;;;!! (scroll-up (1+ (cdr (mouse-coords click)))))
7b611de0 1924;;;!!
dbc4e1c1
JB
1925;;;!! (defun mouse-scroll-down-full ()
1926;;;!! (interactive "@")
1927;;;!! (scroll-down nil))
7b611de0 1928;;;!!
dbc4e1c1
JB
1929;;;!! (defun mouse-scroll-up-full ()
1930;;;!! (interactive "@")
1931;;;!! (scroll-up nil))
7b611de0 1932;;;!!
dbc4e1c1
JB
1933;;;!! (defun mouse-scroll-move-cursor (click)
1934;;;!! (interactive "@e")
1935;;;!! (move-to-window-line (1+ (cdr (mouse-coords click)))))
7b611de0 1936;;;!!
dbc4e1c1
JB
1937;;;!! (defun mouse-scroll-absolute (event)
1938;;;!! (interactive "@e")
1939;;;!! (let* ((pos (car event))
1940;;;!! (position (car pos))
1941;;;!! (length (car (cdr pos))))
1942;;;!! (if (<= length 0) (setq length 1))
1943;;;!! (let* ((scale-factor (max 1 (/ length (/ 8000000 (buffer-size)))))
1944;;;!! (newpos (* (/ (* (/ (buffer-size) scale-factor)
1945;;;!! position)
1946;;;!! length)
1947;;;!! scale-factor)))
1948;;;!! (goto-char newpos)
1949;;;!! (recenter '(4)))))
7b611de0 1950;;;!!
dbc4e1c1
JB
1951;;;!! (defun mouse-scroll-left (click)
1952;;;!! (interactive "@e")
1953;;;!! (scroll-left (1+ (car (mouse-coords click)))))
7b611de0 1954;;;!!
dbc4e1c1
JB
1955;;;!! (defun mouse-scroll-right (click)
1956;;;!! (interactive "@e")
1957;;;!! (scroll-right (1+ (car (mouse-coords click)))))
7b611de0 1958;;;!!
dbc4e1c1
JB
1959;;;!! (defun mouse-scroll-left-full ()
1960;;;!! (interactive "@")
1961;;;!! (scroll-left nil))
7b611de0 1962;;;!!
dbc4e1c1
JB
1963;;;!! (defun mouse-scroll-right-full ()
1964;;;!! (interactive "@")
1965;;;!! (scroll-right nil))
7b611de0 1966;;;!!
dbc4e1c1
JB
1967;;;!! (defun mouse-scroll-move-cursor-horizontally (click)
1968;;;!! (interactive "@e")
1969;;;!! (move-to-column (1+ (car (mouse-coords click)))))
7b611de0 1970;;;!!
dbc4e1c1
JB
1971;;;!! (defun mouse-scroll-absolute-horizontally (event)
1972;;;!! (interactive "@e")
1973;;;!! (let* ((pos (car event))
1974;;;!! (position (car pos))
1975;;;!! (length (car (cdr pos))))
1976;;;!! (set-window-hscroll (selected-window) 33)))
7b611de0 1977;;;!!
dbc4e1c1
JB
1978;;;!! (global-set-key [scroll-bar mouse-1] 'mouse-scroll-up)
1979;;;!! (global-set-key [scroll-bar mouse-2] 'mouse-scroll-absolute)
1980;;;!! (global-set-key [scroll-bar mouse-3] 'mouse-scroll-down)
7b611de0 1981;;;!!
dbc4e1c1
JB
1982;;;!! (global-set-key [vertical-slider mouse-1] 'mouse-scroll-move-cursor)
1983;;;!! (global-set-key [vertical-slider mouse-2] 'mouse-scroll-move-cursor)
1984;;;!! (global-set-key [vertical-slider mouse-3] 'mouse-scroll-move-cursor)
7b611de0 1985;;;!!
dbc4e1c1
JB
1986;;;!! (global-set-key [thumbup mouse-1] 'mouse-scroll-up-full)
1987;;;!! (global-set-key [thumbup mouse-2] 'mouse-scroll-up-full)
1988;;;!! (global-set-key [thumbup mouse-3] 'mouse-scroll-up-full)
7b611de0 1989;;;!!
dbc4e1c1
JB
1990;;;!! (global-set-key [thumbdown mouse-1] 'mouse-scroll-down-full)
1991;;;!! (global-set-key [thumbdown mouse-2] 'mouse-scroll-down-full)
1992;;;!! (global-set-key [thumbdown mouse-3] 'mouse-scroll-down-full)
7b611de0 1993;;;!!
dbc4e1c1
JB
1994;;;!! (global-set-key [horizontal-scroll-bar mouse-1] 'mouse-scroll-left)
1995;;;!! (global-set-key [horizontal-scroll-bar mouse-2]
1996;;;!! 'mouse-scroll-absolute-horizontally)
1997;;;!! (global-set-key [horizontal-scroll-bar mouse-3] 'mouse-scroll-right)
7b611de0 1998;;;!!
dbc4e1c1
JB
1999;;;!! (global-set-key [horizontal-slider mouse-1]
2000;;;!! 'mouse-scroll-move-cursor-horizontally)
2001;;;!! (global-set-key [horizontal-slider mouse-2]
2002;;;!! 'mouse-scroll-move-cursor-horizontally)
2003;;;!! (global-set-key [horizontal-slider mouse-3]
2004;;;!! 'mouse-scroll-move-cursor-horizontally)
7b611de0 2005;;;!!
dbc4e1c1
JB
2006;;;!! (global-set-key [thumbleft mouse-1] 'mouse-scroll-left-full)
2007;;;!! (global-set-key [thumbleft mouse-2] 'mouse-scroll-left-full)
2008;;;!! (global-set-key [thumbleft mouse-3] 'mouse-scroll-left-full)
7b611de0 2009;;;!!
dbc4e1c1
JB
2010;;;!! (global-set-key [thumbright mouse-1] 'mouse-scroll-right-full)
2011;;;!! (global-set-key [thumbright mouse-2] 'mouse-scroll-right-full)
2012;;;!! (global-set-key [thumbright mouse-3] 'mouse-scroll-right-full)
7b611de0 2013;;;!!
dbc4e1c1
JB
2014;;;!! (global-set-key [horizontal-scroll-bar S-mouse-2]
2015;;;!! 'mouse-split-window-horizontally)
2016;;;!! (global-set-key [mode-line S-mouse-2]
2017;;;!! 'mouse-split-window-horizontally)
2018;;;!! (global-set-key [vertical-scroll-bar S-mouse-2]
2019;;;!! 'mouse-split-window)
6b2154de 2020\f
dbc4e1c1
JB
2021;;;!! ;;;;
2022;;;!! ;;;; Here are experimental things being tested. Mouse events
2023;;;!! ;;;; are of the form:
2024;;;!! ;;;; ((x y) window screen-part key-sequence timestamp)
2025;;;!! ;;
2026;;;!! ;;;;
2027;;;!! ;;;; Dynamically track mouse coordinates
2028;;;!! ;;;;
2029;;;!! ;;
2030;;;!! ;;(defun track-mouse (event)
2031;;;!! ;; "Track the coordinates, absolute and relative, of the mouse."
2032;;;!! ;; (interactive "@e")
2033;;;!! ;; (while mouse-grabbed
2034;;;!! ;; (let* ((pos (read-mouse-position (selected-screen)))
2035;;;!! ;; (abs-x (car pos))
2036;;;!! ;; (abs-y (cdr pos))
2037;;;!! ;; (relative-coordinate (coordinates-in-window-p
2038;;;!! ;; (list (car pos) (cdr pos))
2039;;;!! ;; (selected-window))))
2040;;;!! ;; (if (consp relative-coordinate)
2041;;;!! ;; (message "mouse: [%d %d], (%d %d)" abs-x abs-y
2042;;;!! ;; (car relative-coordinate)
2043;;;!! ;; (car (cdr relative-coordinate)))
2044;;;!! ;; (message "mouse: [%d %d]" abs-x abs-y)))))
7b611de0 2045;;;!!
dbc4e1c1
JB
2046;;;!! ;;
2047;;;!! ;; Dynamically put a box around the line indicated by point
2048;;;!! ;;
2049;;;!! ;;
2050;;;!! ;;(require 'backquote)
2051;;;!! ;;
2052;;;!! ;;(defun mouse-select-buffer-line (event)
2053;;;!! ;; (interactive "@e")
2054;;;!! ;; (let ((relative-coordinate
2055;;;!! ;; (coordinates-in-window-p (car event) (selected-window)))
2056;;;!! ;; (abs-y (car (cdr (car event)))))
2057;;;!! ;; (if (consp relative-coordinate)
2058;;;!! ;; (progn
2059;;;!! ;; (save-excursion
2060;;;!! ;; (move-to-window-line (car (cdr relative-coordinate)))
2061;;;!! ;; (x-draw-rectangle
2062;;;!! ;; (selected-screen)
2063;;;!! ;; abs-y 0
2064;;;!! ;; (save-excursion
2065;;;!! ;; (move-to-window-line (car (cdr relative-coordinate)))
2066;;;!! ;; (end-of-line)
2067;;;!! ;; (push-mark nil t)
2068;;;!! ;; (beginning-of-line)
2069;;;!! ;; (- (region-end) (region-beginning))) 1))
2070;;;!! ;; (sit-for 1)
2071;;;!! ;; (x-erase-rectangle (selected-screen))))))
2072;;;!! ;;
2073;;;!! ;;(defvar last-line-drawn nil)
2074;;;!! ;;(defvar begin-delim "[^ \t]")
2075;;;!! ;;(defvar end-delim "[^ \t]")
2076;;;!! ;;
2077;;;!! ;;(defun mouse-boxing (event)
2078;;;!! ;; (interactive "@e")
2079;;;!! ;; (save-excursion
2080;;;!! ;; (let ((screen (selected-screen)))
2081;;;!! ;; (while (= (x-mouse-events) 0)
2082;;;!! ;; (let* ((pos (read-mouse-position screen))
2083;;;!! ;; (abs-x (car pos))
2084;;;!! ;; (abs-y (cdr pos))
2085;;;!! ;; (relative-coordinate
b2013aad 2086;;;!! ;; (coordinates-in-window-p `(,abs-x ,abs-y)
dbc4e1c1
JB
2087;;;!! ;; (selected-window)))
2088;;;!! ;; (begin-reg nil)
2089;;;!! ;; (end-reg nil)
2090;;;!! ;; (end-column nil)
2091;;;!! ;; (begin-column nil))
2092;;;!! ;; (if (and (consp relative-coordinate)
2093;;;!! ;; (or (not last-line-drawn)
2094;;;!! ;; (not (= last-line-drawn abs-y))))
2095;;;!! ;; (progn
2096;;;!! ;; (move-to-window-line (car (cdr relative-coordinate)))
2097;;;!! ;; (if (= (following-char) 10)
2098;;;!! ;; ()
2099;;;!! ;; (progn
2100;;;!! ;; (setq begin-reg (1- (re-search-forward end-delim)))
2101;;;!! ;; (setq begin-column (1- (current-column)))
2102;;;!! ;; (end-of-line)
2103;;;!! ;; (setq end-reg (1+ (re-search-backward begin-delim)))
2104;;;!! ;; (setq end-column (1+ (current-column)))
2105;;;!! ;; (message "%s" (buffer-substring begin-reg end-reg))
2106;;;!! ;; (x-draw-rectangle screen
2107;;;!! ;; (setq last-line-drawn abs-y)
2108;;;!! ;; begin-column
2109;;;!! ;; (- end-column begin-column) 1))))))))))
2110;;;!! ;;
2111;;;!! ;;(defun mouse-erase-box ()
2112;;;!! ;; (interactive)
2113;;;!! ;; (if last-line-drawn
2114;;;!! ;; (progn
2115;;;!! ;; (x-erase-rectangle (selected-screen))
2116;;;!! ;; (setq last-line-drawn nil))))
7b611de0 2117;;;!!
dbc4e1c1
JB
2118;;;!! ;;; (defun test-x-rectangle ()
2119;;;!! ;;; (use-local-mouse-map (setq rectangle-test-map (make-sparse-keymap)))
2120;;;!! ;;; (define-key rectangle-test-map mouse-motion-button-left 'mouse-boxing)
2121;;;!! ;;; (define-key rectangle-test-map mouse-button-left-up 'mouse-erase-box))
7b611de0 2122;;;!!
dbc4e1c1
JB
2123;;;!! ;;
2124;;;!! ;; Here is how to do double clicking in lisp. About to change.
2125;;;!! ;;
7b611de0 2126;;;!!
dbc4e1c1
JB
2127;;;!! (defvar double-start nil)
2128;;;!! (defconst double-click-interval 300
2129;;;!! "Max ticks between clicks")
7b611de0 2130;;;!!
dbc4e1c1
JB
2131;;;!! (defun double-down (event)
2132;;;!! (interactive "@e")
2133;;;!! (if double-start
2134;;;!! (let ((interval (- (nth 4 event) double-start)))
2135;;;!! (if (< interval double-click-interval)
2136;;;!! (progn
2137;;;!! (backward-up-list 1)
2138;;;!! ;; (message "Interval %d" interval)
2139;;;!! (sleep-for 1)))
2140;;;!! (setq double-start nil))
2141;;;!! (setq double-start (nth 4 event))))
7b611de0 2142;;;!!
dbc4e1c1
JB
2143;;;!! (defun double-up (event)
2144;;;!! (interactive "@e")
2145;;;!! (and double-start
2146;;;!! (> (- (nth 4 event ) double-start) double-click-interval)
2147;;;!! (setq double-start nil)))
7b611de0 2148;;;!!
dbc4e1c1
JB
2149;;;!! ;;; (defun x-test-doubleclick ()
2150;;;!! ;;; (use-local-mouse-map (setq doubleclick-test-map (make-sparse-keymap)))
2151;;;!! ;;; (define-key doubleclick-test-map mouse-button-left 'double-down)
2152;;;!! ;;; (define-key doubleclick-test-map mouse-button-left-up 'double-up))
7b611de0 2153;;;!!
dbc4e1c1 2154;;;!! ;;
5ba2dc3f 2155;;;!! ;; This scrolls while button is depressed. Use preferable in scroll bar.
dbc4e1c1 2156;;;!! ;;
7b611de0 2157;;;!!
dbc4e1c1
JB
2158;;;!! (defvar scrolled-lines 0)
2159;;;!! (defconst scroll-speed 1)
7b611de0 2160;;;!!
dbc4e1c1
JB
2161;;;!! (defun incr-scroll-down (event)
2162;;;!! (interactive "@e")
2163;;;!! (setq scrolled-lines 0)
2164;;;!! (incremental-scroll scroll-speed))
7b611de0 2165;;;!!
dbc4e1c1
JB
2166;;;!! (defun incr-scroll-up (event)
2167;;;!! (interactive "@e")
2168;;;!! (setq scrolled-lines 0)
2169;;;!! (incremental-scroll (- scroll-speed)))
7b611de0 2170;;;!!
dbc4e1c1
JB
2171;;;!! (defun incremental-scroll (n)
2172;;;!! (while (= (x-mouse-events) 0)
2173;;;!! (setq scrolled-lines (1+ (* scroll-speed scrolled-lines)))
2174;;;!! (scroll-down n)
2175;;;!! (sit-for 300 t)))
7b611de0 2176;;;!!
dbc4e1c1
JB
2177;;;!! (defun incr-scroll-stop (event)
2178;;;!! (interactive "@e")
2179;;;!! (message "Scrolled %d lines" scrolled-lines)
2180;;;!! (setq scrolled-lines 0)
2181;;;!! (sleep-for 1))
7b611de0 2182;;;!!
dbc4e1c1
JB
2183;;;!! ;;; (defun x-testing-scroll ()
2184;;;!! ;;; (let ((scrolling-map (function mouse-vertical-scroll-bar-prefix)))
2185;;;!! ;;; (define-key scrolling-map mouse-button-left 'incr-scroll-down)
2186;;;!! ;;; (define-key scrolling-map mouse-button-right 'incr-scroll-up)
2187;;;!! ;;; (define-key scrolling-map mouse-button-left-up 'incr-scroll-stop)
2188;;;!! ;;; (define-key scrolling-map mouse-button-right-up 'incr-scroll-stop)))
7b611de0 2189;;;!!
dbc4e1c1
JB
2190;;;!! ;;
2191;;;!! ;; Some playthings suitable for picture mode? They need work.
2192;;;!! ;;
7b611de0 2193;;;!!
dbc4e1c1
JB
2194;;;!! (defun mouse-kill-rectangle (event)
2195;;;!! "Kill the rectangle between point and the mouse cursor."
2196;;;!! (interactive "@e")
2197;;;!! (let ((point-save (point)))
2198;;;!! (save-excursion
2199;;;!! (mouse-set-point event)
2200;;;!! (push-mark nil t)
2201;;;!! (if (> point-save (point))
2202;;;!! (kill-rectangle (point) point-save)
2203;;;!! (kill-rectangle point-save (point))))))
7b611de0 2204;;;!!
dbc4e1c1
JB
2205;;;!! (defun mouse-open-rectangle (event)
2206;;;!! "Kill the rectangle between point and the mouse cursor."
2207;;;!! (interactive "@e")
2208;;;!! (let ((point-save (point)))
2209;;;!! (save-excursion
2210;;;!! (mouse-set-point event)
2211;;;!! (push-mark nil t)
2212;;;!! (if (> point-save (point))
2213;;;!! (open-rectangle (point) point-save)
2214;;;!! (open-rectangle point-save (point))))))
7b611de0 2215;;;!!
dbc4e1c1 2216;;;!! ;; Must be a better way to do this.
7b611de0 2217;;;!!
dbc4e1c1
JB
2218;;;!! (defun mouse-multiple-insert (n char)
2219;;;!! (while (> n 0)
2220;;;!! (insert char)
2221;;;!! (setq n (1- n))))
7b611de0 2222;;;!!
dbc4e1c1 2223;;;!! ;; What this could do is not finalize until button was released.
7b611de0 2224;;;!!
dbc4e1c1
JB
2225;;;!! (defun mouse-move-text (event)
2226;;;!! "Move text from point to cursor position, inserting spaces."
2227;;;!! (interactive "@e")
2228;;;!! (let* ((relative-coordinate
2229;;;!! (coordinates-in-window-p (car event) (selected-window))))
2230;;;!! (if (consp relative-coordinate)
2231;;;!! (cond ((> (current-column) (car relative-coordinate))
2232;;;!! (delete-char
2233;;;!! (- (car relative-coordinate) (current-column))))
2234;;;!! ((< (current-column) (car relative-coordinate))
2235;;;!! (mouse-multiple-insert
2236;;;!! (- (car relative-coordinate) (current-column)) " "))
2237;;;!! ((= (current-column) (car relative-coordinate)) (ding))))))
07a78410 2238\f
f936ae06
RS
2239;; Choose a completion with the mouse.
2240
2241(defun mouse-choose-completion (event)
49e61c42 2242 "Click on an alternative in the `*Completions*' buffer to choose it."
f936ae06 2243 (interactive "e")
33c448cd
RS
2244 ;; Give temporary modes such as isearch a chance to turn off.
2245 (run-hooks 'mouse-leave-buffer-hook)
d89a4a47 2246 (let ((buffer (window-buffer))
02680e9b
RS
2247 choice
2248 base-size)
f936ae06
RS
2249 (save-excursion
2250 (set-buffer (window-buffer (posn-window (event-start event))))
f36f4e9e
RS
2251 (if completion-reference-buffer
2252 (setq buffer completion-reference-buffer))
02680e9b 2253 (setq base-size completion-base-size)
f936ae06
RS
2254 (save-excursion
2255 (goto-char (posn-point (event-start event)))
b6be5d95 2256 (let (beg end)
9a43a594
RS
2257 (if (and (not (eobp)) (get-text-property (point) 'mouse-face))
2258 (setq end (point) beg (1+ (point))))
2259 (if (null beg)
2260 (error "No completion here"))
2261 (setq beg (previous-single-property-change beg 'mouse-face))
2f5ed2e8
RS
2262 (setq end (or (next-single-property-change end 'mouse-face)
2263 (point-max)))
b6be5d95 2264 (setq choice (buffer-substring beg end)))))
73e2025f
RS
2265 (let ((owindow (selected-window)))
2266 (select-window (posn-window (event-start event)))
874a2cbd
RS
2267 (if (and (one-window-p t 'selected-frame)
2268 (window-dedicated-p (selected-window)))
2269 ;; This is a special buffer's frame
2270 (iconify-frame (selected-frame))
2271 (or (window-dedicated-p (selected-window))
2272 (bury-buffer)))
73e2025f 2273 (select-window owindow))
02680e9b 2274 (choose-completion-string choice buffer base-size)))
f936ae06 2275\f
07a78410
RS
2276;; Font selection.
2277
0eb9fef3
RS
2278(defun font-menu-add-default ()
2279 (let* ((default (cdr (assq 'font (frame-parameters (selected-frame)))))
2280 (font-alist x-fixed-font-alist)
0d94f5ca 2281 (elt (or (assoc "Misc" font-alist) (nth 1 font-alist))))
0eb9fef3
RS
2282 (if (assoc "Default" elt)
2283 (delete (assoc "Default" elt) elt))
2284 (setcdr elt
6b8e486e 2285 (cons (list "Default" default)
0eb9fef3
RS
2286 (cdr elt)))))
2287
07a78410
RS
2288(defvar x-fixed-font-alist
2289 '("Font menu"
2290 ("Misc"
19d973e8
RS
2291 ;; For these, we specify the pixel height and width.
2292 ("fixed" "fixed")
2293 ("6x10" "-misc-fixed-medium-r-normal--10-*-*-*-c-60-iso8859-1" "6x10")
2294 ("6x12"
2295 "-misc-fixed-medium-r-semicondensed--12-*-*-*-c-60-iso8859-1" "6x12")
2296 ("6x13"
2297 "-misc-fixed-medium-r-semicondensed--13-*-*-*-c-60-iso8859-1" "6x13")
2298 ("7x13" "-misc-fixed-medium-r-normal--13-*-*-*-c-70-iso8859-1" "7x13")
2299 ("7x14" "-misc-fixed-medium-r-normal--14-*-*-*-c-70-iso8859-1" "7x14")
2300 ("8x13" "-misc-fixed-medium-r-normal--13-*-*-*-c-80-iso8859-1" "8x13")
2301 ("9x15" "-misc-fixed-medium-r-normal--15-*-*-*-c-90-iso8859-1" "9x15")
2302 ("10x20" "-misc-fixed-medium-r-normal--20-*-*-*-c-100-iso8859-1" "10x20")
2303 ("11x18" "-misc-fixed-medium-r-normal--18-*-*-*-c-110-iso8859-1" "11x18")
2304 ("12x24" "-misc-fixed-medium-r-normal--24-*-*-*-c-120-iso8859-1" "12x24")
fa21fdec 2305 ("")
f29c3695
RS
2306 ("clean 5x8"
2307 "-schumacher-clean-medium-r-normal--8-*-*-*-c-50-iso8859-1")
2308 ("clean 6x8"
2309 "-schumacher-clean-medium-r-normal--8-*-*-*-c-60-iso8859-1")
19d973e8
RS
2310 ("clean 8x8"
2311 "-schumacher-clean-medium-r-normal--8-*-*-*-c-80-iso8859-1")
2312 ("clean 8x10"
2313 "-schumacher-clean-medium-r-normal--10-*-*-*-c-80-iso8859-1")
2314 ("clean 8x14"
2315 "-schumacher-clean-medium-r-normal--14-*-*-*-c-80-iso8859-1")
2316 ("clean 8x16"
2317 "-schumacher-clean-medium-r-normal--16-*-*-*-c-80-iso8859-1")
fa21fdec 2318 ("")
29a3028d 2319 ("sony 8x16" "-sony-fixed-medium-r-normal--16-*-*-*-c-80-iso8859-1")
07a78410
RS
2320;;; We don't seem to have these; who knows what they are.
2321;;; ("fg-18" "fg-18")
2322;;; ("fg-25" "fg-25")
29a3028d
DL
2323 ("lucidasanstypewriter-12" "-b&h-lucidatypewriter-medium-r-normal-sans-*-120-*-*-*-*-iso8859-1")
2324 ("lucidasanstypewriter-bold-14" "-b&h-lucidatypewriter-bold-r-normal-sans-*-140-*-*-*-*-iso8859-1")
2325 ("lucidasanstypewriter-bold-24"
2326 "-b&h-lucidatypewriter-bold-r-normal-sans-*-240-*-*-*-*-iso8859-1")
07a78410
RS
2327;;; ("lucidatypewriter-bold-r-24" "-b&h-lucidatypewriter-bold-r-normal-sans-24-240-75-75-m-140-iso8859-1")
2328;;; ("fixed-medium-20" "-misc-fixed-medium-*-*-*-20-*-*-*-*-*-*-*")
29a3028d 2329 )
07a78410 2330 ("Courier"
19d973e8 2331 ;; For these, we specify the point height.
82c048a9
RS
2332 ("8" "-adobe-courier-medium-r-normal--*-80-*-*-m-*-iso8859-1")
2333 ("10" "-adobe-courier-medium-r-normal--*-100-*-*-m-*-iso8859-1")
2334 ("12" "-adobe-courier-medium-r-normal--*-120-*-*-m-*-iso8859-1")
2335 ("14" "-adobe-courier-medium-r-normal--*-140-*-*-m-*-iso8859-1")
2336 ("18" "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1")
2337 ("24" "-adobe-courier-medium-r-normal--*-240-*-*-m-*-iso8859-1")
2338 ("8 bold" "-adobe-courier-bold-r-normal--*-80-*-*-m-*-iso8859-1")
2339 ("10 bold" "-adobe-courier-bold-r-normal--*-100-*-*-m-*-iso8859-1")
2340 ("12 bold" "-adobe-courier-bold-r-normal--*-120-*-*-m-*-iso8859-1")
2341 ("14 bold" "-adobe-courier-bold-r-normal--*-140-*-*-m-*-iso8859-1")
2342 ("18 bold" "-adobe-courier-bold-r-normal--*-180-*-*-m-*-iso8859-1")
2343 ("24 bold" "-adobe-courier-bold-r-normal--*-240-*-*-m-*-iso8859-1")
2344 ("8 slant" "-adobe-courier-medium-o-normal--*-80-*-*-m-*-iso8859-1")
2345 ("10 slant" "-adobe-courier-medium-o-normal--*-100-*-*-m-*-iso8859-1")
2346 ("12 slant" "-adobe-courier-medium-o-normal--*-120-*-*-m-*-iso8859-1")
2347 ("14 slant" "-adobe-courier-medium-o-normal--*-140-*-*-m-*-iso8859-1")
2348 ("18 slant" "-adobe-courier-medium-o-normal--*-180-*-*-m-*-iso8859-1")
2349 ("24 slant" "-adobe-courier-medium-o-normal--*-240-*-*-m-*-iso8859-1")
2350 ("8 bold slant" "-adobe-courier-bold-o-normal--*-80-*-*-m-*-iso8859-1")
2351 ("10 bold slant" "-adobe-courier-bold-o-normal--*-100-*-*-m-*-iso8859-1")
2352 ("12 bold slant" "-adobe-courier-bold-o-normal--*-120-*-*-m-*-iso8859-1")
2353 ("14 bold slant" "-adobe-courier-bold-o-normal--*-140-*-*-m-*-iso8859-1")
2354 ("18 bold slant" "-adobe-courier-bold-o-normal--*-180-*-*-m-*-iso8859-1")
2355 ("24 bold slant" "-adobe-courier-bold-o-normal--*-240-*-*-m-*-iso8859-1"))
07a78410
RS
2356 )
2357 "X fonts suitable for use in Emacs.")
2358
1900a92b 2359(defun mouse-set-font (&rest fonts)
51a02226 2360 "Select an emacs font from a list of known good fonts and fontsets."
07a78410 2361 (interactive
8eb1dc02
RS
2362 (progn (unless (display-multi-font-p)
2363 (error "Cannot change fonts on this display"))
2364 (x-popup-menu
91c51412
LT
2365 (if (listp last-nonmenu-event)
2366 last-nonmenu-event
2367 (list '(0 0) (selected-window)))
8eb1dc02
RS
2368 ;; Append list of fontsets currently defined.
2369 (append x-fixed-font-alist (list (generate-fontset-menu))))))
df4de8c6
KH
2370 (if fonts
2371 (let (font)
2372 (while fonts
2373 (condition-case nil
2374 (progn
3fadec1a 2375 (set-default-font (car fonts))
df4de8c6
KH
2376 (setq font (car fonts))
2377 (setq fonts nil))
3fadec1a
RS
2378 (error
2379 (setq fonts (cdr fonts)))))
df4de8c6 2380 (if (null font)
8eb1dc02 2381 (error "Font not found")))))
cc0a8174
JB
2382\f
2383;;; Bindings for mouse commands.
2384
fcfc3c63 2385(define-key global-map [down-mouse-1] 'mouse-drag-region)
dbc4e1c1 2386(global-set-key [mouse-1] 'mouse-set-point)
dbc4e1c1 2387(global-set-key [drag-mouse-1] 'mouse-set-region)
fcfc3c63 2388
e37de120
RS
2389;; These are tested for in mouse-drag-region.
2390(global-set-key [double-mouse-1] 'mouse-set-point)
2391(global-set-key [triple-mouse-1] 'mouse-set-point)
2392
76693d12
KS
2393;; Clicking on the fringes causes hscrolling:
2394(global-set-key [left-fringe mouse-1] 'mouse-set-point)
2395(global-set-key [right-fringe mouse-1] 'mouse-set-point)
2396
dbc4e1c1
JB
2397(global-set-key [mouse-2] 'mouse-yank-at-click)
2398(global-set-key [mouse-3] 'mouse-save-then-kill)
8b34e79d 2399
dbc4e1c1
JB
2400;; By binding these to down-going events, we let the user use the up-going
2401;; event to make the selection, saving a click.
08a1c178
RS
2402(global-set-key [C-down-mouse-1] 'mouse-buffer-menu)
2403(if (not (eq system-type 'ms-dos))
2404 (global-set-key [S-down-mouse-1] 'mouse-set-font))
eef805d7 2405;; C-down-mouse-2 is bound in facemenu.el.
de420e82 2406(global-set-key [C-down-mouse-3] 'mouse-popup-menubar-stuff)
95132d1c 2407
07a78410 2408
8b34e79d
RS
2409;; Replaced with dragging mouse-1
2410;; (global-set-key [S-mouse-1] 'mouse-set-mark)
947da0c4 2411
06a8c9f8
EZ
2412;; Binding mouse-1 to mouse-select-window when on mode-, header-, or
2413;; vertical-line prevents Emacs from signaling an error when the mouse
2414;; button is released after dragging these lines, on non-toolkit
2415;; versions.
3c2dd2c0 2416(global-set-key [mode-line mouse-1] 'mouse-select-window)
544e7e73
RS
2417(global-set-key [mode-line drag-mouse-1] 'mouse-select-window)
2418(global-set-key [mode-line down-mouse-1] 'mouse-drag-mode-line)
b0d22e20 2419(global-set-key [header-line down-mouse-1] 'mouse-drag-header-line)
06a8c9f8 2420(global-set-key [header-line mouse-1] 'mouse-select-window)
3c2dd2c0 2421(global-set-key [mode-line mouse-2] 'mouse-delete-other-windows)
dbc4e1c1 2422(global-set-key [mode-line mouse-3] 'mouse-delete-window)
3c2dd2c0 2423(global-set-key [mode-line C-mouse-2] 'mouse-split-window-horizontally)
9926ab64 2424(global-set-key [vertical-scroll-bar C-mouse-2] 'mouse-split-window-vertically)
b6522df6 2425(global-set-key [vertical-line C-mouse-2] 'mouse-split-window-vertically)
08a1c178
RS
2426(global-set-key [vertical-line down-mouse-1] 'mouse-drag-vertical-line)
2427(global-set-key [vertical-line mouse-1] 'mouse-select-window)
49116ac0
JB
2428
2429(provide 'mouse)
2430
2fe85227
DL
2431;; This file contains the functionality of the old mldrag.el.
2432(defalias 'mldrag-drag-mode-line 'mouse-drag-mode-line)
2433(defalias 'mldrag-drag-vertical-line 'mouse-drag-vertical-line)
342a1e7b
SM
2434(make-obsolete 'mldrag-drag-mode-line 'mouse-drag-mode-line "21.1")
2435(make-obsolete 'mldrag-drag-vertical-line 'mouse-drag-vertical-line "21.1")
2fe85227
DL
2436(provide 'mldrag)
2437
ab5796a9 2438;;; arch-tag: 9a710ce1-914a-4923-9b81-697f7bf82ab3
6594deb0 2439;;; mouse.el ends here