(Fpos_visible_in_window_p): Do something reasonable
[bpt/emacs.git] / lisp / mouse.el
CommitLineData
6594deb0 1;;; mouse.el --- window system-independent mouse support.
84176303 2
d733c5ec 3;;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
eea8d4ef 4
84176303 5;; Maintainer: FSF
84176303
ER
6;; Keywords: hardware
7
cc0a8174 8;;; This file is part of GNU Emacs.
72ea54a4 9
cc0a8174
JB
10;;; GNU Emacs is free software; you can redistribute it and/or modify
11;;; it under the terms of the GNU General Public License as published by
87ef29fd 12;;; the Free Software Foundation; either version 2, or (at your option)
cc0a8174 13;;; any later version.
72ea54a4 14
cc0a8174
JB
15;;; GNU Emacs is distributed in the hope that it will be useful,
16;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;;; GNU General Public License for more details.
72ea54a4 19
cc0a8174
JB
20;;; You should have received a copy of the GNU General Public License
21;;; along with GNU Emacs; see the file COPYING. If not, write to
22;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
72ea54a4 23
edbd2f74
ER
24;;; Commentary:
25
26;; This package provides various useful commands (including help
27;; system access) through the mouse. All this code assumes that mouse
28;; interpretation has been abstracted into Emacs input events.
29;;
30;; The code is rather X-dependent.
31
aae56ea7
ER
32;;; Code:
33
cc0a8174 34;;; Utility functions.
72ea54a4 35
cc0a8174
JB
36;;; Indent track-mouse like progn.
37(put 'track-mouse 'lisp-indent-function 0)
72ea54a4 38
50f58001
RS
39(defvar mouse-yank-at-point nil
40 "*If non-nil, mouse yank commands yank at point instead of at click.")
cc0a8174 41\f
d65147f6
KH
42(defun mouse-minibuffer-check (event)
43 (let ((w (posn-window (event-start event))))
44 (and (window-minibuffer-p w)
45 (not (minibuffer-window-active-p w))
46 (error "Minibuffer window is not active"))))
47
cc0a8174 48(defun mouse-delete-window (click)
947da0c4 49 "Delete the window you click on.
cc0a8174 50This must be bound to a mouse click."
ec558adc 51 (interactive "e")
d65147f6 52 (mouse-minibuffer-check click)
b5370f03 53 (delete-window (posn-window (event-start click))))
cc0a8174 54
3c2dd2c0
RS
55(defun mouse-select-window (click)
56 "Select the window clicked on; don't move point."
57 (interactive "e")
d65147f6 58 (mouse-minibuffer-check click)
3c2dd2c0
RS
59 (let ((oframe (selected-frame))
60 (frame (window-frame (posn-window (event-start click)))))
61 (select-window (posn-window (event-start click)))
62 (raise-frame frame)
63 (select-frame frame)
64 (or (eq frame oframe)
65 (set-mouse-position (selected-frame) (1- (frame-width)) 0))
66 (unfocus-frame)))
67
b0f3a26b
JB
68(defun mouse-tear-off-window (click)
69 "Delete the window clicked on, and create a new frame displaying its buffer."
70 (interactive "e")
d65147f6 71 (mouse-minibuffer-check click)
b0f3a26b
JB
72 (let* ((window (posn-window (event-start click)))
73 (buf (window-buffer window))
01a911e3 74 (frame (make-frame)))
b0f3a26b
JB
75 (select-frame frame)
76 (switch-to-buffer buf)
77 (delete-window window)))
78
b5370f03 79(defun mouse-delete-other-windows ()
947da0c4 80 "Delete all window except the one you click on."
b5370f03 81 (interactive "@")
cc0a8174 82 (delete-other-windows))
72ea54a4 83
cc0a8174
JB
84(defun mouse-split-window-vertically (click)
85 "Select Emacs window mouse is on, then split it vertically in half.
86The window is split at the line clicked on.
87This command must be bound to a mouse click."
947da0c4 88 (interactive "@e")
d65147f6 89 (mouse-minibuffer-check click)
b5370f03
JB
90 (let ((start (event-start click)))
91 (select-window (posn-window start))
85d6b80b 92 (let ((new-height (1+ (cdr (posn-col-row (event-end click)))))
5ba2dc3f
JB
93 (first-line window-min-height)
94 (last-line (- (window-height) window-min-height)))
95 (if (< last-line first-line)
0a50b993 96 (error "Window too short to split")
5ba2dc3f
JB
97 (split-window-vertically
98 (min (max new-height first-line) last-line))))))
cc0a8174 99
947da0c4
RS
100(defun mouse-split-window-horizontally (click)
101 "Select Emacs window mouse is on, then split it horizontally in half.
102The window is split at the column clicked on.
103This command must be bound to a mouse click."
104 (interactive "@e")
d65147f6 105 (mouse-minibuffer-check click)
5ba2dc3f
JB
106 (let ((start (event-start click)))
107 (select-window (posn-window start))
108 (let ((new-width (1+ (car (posn-col-row (event-end click)))))
109 (first-col window-min-width)
110 (last-col (- (window-width) window-min-width)))
111 (if (< last-col first-col)
0a50b993 112 (error "Window too narrow to split")
5ba2dc3f
JB
113 (split-window-horizontally
114 (min (max new-width first-col) last-col))))))
947da0c4 115
2a5fa27b 116(defun mouse-set-point (event)
cc0a8174 117 "Move point to the position clicked on with the mouse.
2a5fa27b 118This should be bound to a mouse click event type."
ec558adc 119 (interactive "e")
d65147f6 120 (mouse-minibuffer-check event)
2a5fa27b
RS
121 ;; Use event-end in case called from mouse-drag-region.
122 ;; If EVENT is a click, event-end and event-start give same value.
123 (let ((posn (event-end event)))
0a50b993
RS
124 (if (not (windowp (posn-window posn)))
125 (error "Cursor not in text area of window"))
b5370f03
JB
126 (select-window (posn-window posn))
127 (if (numberp (posn-point posn))
128 (goto-char (posn-point posn)))))
cc0a8174 129
652ccd35 130(defun mouse-set-region (click)
e37de120 131 "Set the region to the text dragged over, and copy to kill ring.
2a5fa27b 132This should be bound to a mouse drag event."
652ccd35 133 (interactive "e")
d65147f6 134 (mouse-minibuffer-check click)
652ccd35
RS
135 (let ((posn (event-start click))
136 (end (event-end click)))
137 (select-window (posn-window posn))
138 (if (numberp (posn-point posn))
139 (goto-char (posn-point posn)))
fcfc3c63
RS
140 ;; If mark is highlighted, no need to bounce the cursor.
141 (or (and transient-mark-mode
142 (eq (framep (selected-frame)) 'x))
143 (sit-for 1))
652ccd35 144 (push-mark)
1cc8a3f4 145 (set-mark (point))
652ccd35 146 (if (numberp (posn-point end))
e37de120
RS
147 (goto-char (posn-point end)))
148 ;; Don't set this-command to kill-region, so that a following
149 ;; C-w will not double the text in the kill ring.
150 (let (this-command)
151 (copy-region-as-kill (mark) (point)))))
652ccd35 152
600c6e3a
JB
153(defvar mouse-scroll-delay 0.25
154 "*The pause between scroll steps caused by mouse drags, in seconds.
155If you drag the mouse beyond the edge of a window, Emacs scrolls the
156window to bring the text beyond that edge into view, with a delay of
157this many seconds between scroll steps. Scrolling stops when you move
158the mouse back into the window, or release the button.
159This variable's value may be non-integral.
160Setting this to zero causes Emacs to scroll as fast as it can.")
161
e919a622
RS
162(defun mouse-scroll-subr (window jump &optional overlay start)
163 "Scroll the window WINDOW, JUMP lines at a time, until new input arrives.
600c6e3a
JB
164If OVERLAY is an overlay, let it stretch from START to the far edge of
165the newly visible text.
166Upon exit, point is at the far edge of the newly visible text."
4e399a53
RS
167 (let ((opoint (point)))
168 (while (progn
169 (goto-char (window-start window))
170 (if (not (zerop (vertical-motion jump window)))
171 (progn
172 (set-window-start window (point))
173 (if (natnump jump)
174 (progn
175 (goto-char (window-end window))
176 ;; window-end doesn't reflect the window's new
177 ;; start position until the next redisplay. Hurrah.
178 (vertical-motion (1- jump) window))
179 (goto-char (window-start window)))
180 (if overlay
181 (move-overlay overlay start (point)))
182 ;; Now that we have scrolled WINDOW properly,
183 ;; put point back where it was for the redisplay
184 ;; so that we don't mess up the selected window.
185 (or (eq window (selected-window))
186 (goto-char opoint))
d2287ded 187 (sit-for mouse-scroll-delay)))))
4e399a53
RS
188 (or (eq window (selected-window))
189 (goto-char opoint))))
fcfc3c63 190
600c6e3a
JB
191(defvar mouse-drag-overlay (make-overlay 1 1))
192(overlay-put mouse-drag-overlay 'face 'region)
193
dd524dbd 194(defvar mouse-selection-click-count 0)
eb6ff46f 195
600c6e3a 196(defun mouse-drag-region (start-event)
bcd5aef1 197 "Set the region to the text that the mouse is dragged over.
78210c95
RS
198Highlight the drag area as you move the mouse.
199This must be bound to a button-down mouse event.
200In Transient Mark mode, the highlighting remains once you
201release the mouse button. Otherwise, it does not."
bcd5aef1 202 (interactive "e")
d65147f6 203 (mouse-minibuffer-check start-event)
600c6e3a
JB
204 (let* ((start-posn (event-start start-event))
205 (start-point (posn-point start-posn))
206 (start-window (posn-window start-posn))
b846d039 207 (start-frame (window-frame start-window))
600c6e3a
JB
208 (bounds (window-edges start-window))
209 (top (nth 1 bounds))
210 (bottom (if (window-minibuffer-p start-window)
211 (nth 3 bounds)
212 ;; Don't count the mode line.
e37de120
RS
213 (1- (nth 3 bounds))))
214 (click-count (1- (event-click-count start-event))))
eb6ff46f 215 (setq mouse-selection-click-count click-count)
b80f1928 216 (mouse-set-point start-event)
e37de120
RS
217 (let ((range (mouse-start-end start-point start-point click-count)))
218 (move-overlay mouse-drag-overlay (car range) (nth 1 range)
219 (window-buffer start-window)))
f767385c 220 (deactivate-mark)
600c6e3a 221 (let (event end end-point)
bcd5aef1 222 (track-mouse
600c6e3a 223 (while (progn
b846d039
JB
224 (setq event (read-event))
225 (or (mouse-movement-p event)
226 (eq (car-safe event) 'switch-frame)))
b846d039
JB
227 (if (eq (car-safe event) 'switch-frame)
228 nil
229 (setq end (event-end event)
230 end-point (posn-point end))
231
232 (cond
b846d039
JB
233 ;; Are we moving within the original window?
234 ((and (eq (posn-window end) start-window)
235 (integer-or-marker-p end-point))
236 (goto-char end-point)
e37de120
RS
237 (let ((range (mouse-start-end start-point (point) click-count)))
238 (move-overlay mouse-drag-overlay (car range) (nth 1 range))))
b846d039 239
50e527bc
KH
240 (t
241 (let ((mouse-row (cdr (cdr (mouse-position)))))
b846d039 242 (cond
50e527bc 243 ((null mouse-row))
b846d039 244 ((< mouse-row top)
e919a622
RS
245 (mouse-scroll-subr start-window (- mouse-row top)
246 mouse-drag-overlay start-point))
d2287ded 247 ((>= mouse-row bottom)
e919a622 248 (mouse-scroll-subr start-window (1+ (- mouse-row bottom))
50e527bc 249 mouse-drag-overlay start-point)))))))))
4e399a53
RS
250 (if (consp event)
251;;; When we scroll into the mode line or menu bar, or out of the window,
252;;; we get events that don't fit these criteria.
253;;; (eq (get (event-basic-type event) 'event-kind) 'mouse-click)
254;;; (eq (posn-window (event-end event)) start-window)
255;;; (numberp (posn-point (event-end event)))
e37de120 256 (let ((fun (key-binding (vector (car event)))))
4e399a53
RS
257 (if (not (= (overlay-start mouse-drag-overlay)
258 (overlay-end mouse-drag-overlay)))
6452d8a6 259 (let (last-command this-command)
4e399a53 260 (push-mark (overlay-start mouse-drag-overlay) t t)
3544cfc9 261 (goto-char (overlay-end mouse-drag-overlay))
4e399a53
RS
262 (copy-region-as-kill (point) (mark t)))
263 (goto-char (overlay-end mouse-drag-overlay))
264 (setq this-command 'mouse-set-point))))
600c6e3a 265 (delete-overlay mouse-drag-overlay))))
e37de120
RS
266\f
267;; Commands to handle xterm-style multiple clicks.
600c6e3a 268
e37de120
RS
269(defun mouse-skip-word (dir)
270 "Skip over word, over whitespace, or over identical punctuation.
271If DIR is positive skip forward; if negative, skip backward."
272 (let* ((char (following-char))
273 (syntax (char-to-string (char-syntax char))))
274 (if (or (string= syntax "w") (string= syntax " "))
275 (if (< dir 0)
276 (skip-syntax-backward syntax)
277 (skip-syntax-forward syntax))
278 (if (< dir 0)
d89a4a47 279 (while (and (not (bobp)) (= (preceding-char) char))
e37de120 280 (forward-char -1))
d89a4a47 281 (while (and (not (eobp)) (= (following-char) char))
e37de120
RS
282 (forward-char 1))))))
283
284;; Return a list of region bounds based on START and END according to MODE.
285;; If MODE is 0 then set point to (min START END), mark to (max START END).
286;; If MODE is 1 then set point to start of word at (min START END),
287;; mark to end of word at (max START END).
288;; If MODE is 2 then do the same for lines.
eb6ff46f 289(defun mouse-start-end (start end mode)
e37de120
RS
290 (if (> start end)
291 (let ((temp start))
292 (setq start end
293 end temp)))
9a974c88 294 (setq mode (mod mode 3))
e37de120
RS
295 (cond ((= mode 0)
296 (list start end))
297 ((and (= mode 1)
298 (= start end)
1ec71583 299 (char-after start)
e37de120 300 (= (char-syntax (char-after start)) ?\())
6f482eec
RS
301 (list start
302 (save-excursion
303 (goto-char start)
304 (forward-sexp 1)
305 (point))))
e37de120
RS
306 ((and (= mode 1)
307 (= start end)
1ec71583 308 (char-after start)
e37de120
RS
309 (= (char-syntax (char-after start)) ?\)))
310 (list (save-excursion
311 (goto-char (1+ start))
d89a4a47
RS
312 (backward-sexp 1)
313 (point))
e37de120
RS
314 (1+ start)))
315 ((= mode 1)
316 (list (save-excursion
317 (goto-char start)
318 (mouse-skip-word -1)
319 (point))
320 (save-excursion
321 (goto-char end)
322 (mouse-skip-word 1)
323 (point))))
324 ((= mode 2)
325 (list (save-excursion
326 (goto-char start)
327 (beginning-of-line 1)
328 (point))
329 (save-excursion
330 (goto-char end)
331 (forward-line 1)
332 (point))))))
e66feb07 333\f
3f26b32a
RS
334;; Subroutine: set the mark where CLICK happened,
335;; but don't do anything else.
336(defun mouse-set-mark-fast (click)
d65147f6 337 (mouse-minibuffer-check click)
3f26b32a
RS
338 (let ((posn (event-start click)))
339 (select-window (posn-window posn))
340 (if (numberp (posn-point posn))
341 (push-mark (posn-point posn) t t))))
342
343;; Momentarily show where the mark is, if highlighting doesn't show it.
344(defun mouse-show-mark ()
345 (or transient-mark-mode
346 (save-excursion
347 (goto-char (mark t))
348 (sit-for 1))))
349
cc0a8174
JB
350(defun mouse-set-mark (click)
351 "Set mark at the position clicked on with the mouse.
352Display cursor at that position for a second.
353This must be bound to a mouse click."
ec558adc 354 (interactive "e")
72ea54a4
RS
355 (let ((point-save (point)))
356 (unwind-protect
cc0a8174 357 (progn (mouse-set-point click)
897897e3
RS
358 (push-mark nil t t)
359 (or transient-mark-mode
360 (sit-for 1)))
72ea54a4
RS
361 (goto-char point-save))))
362
cc0a8174
JB
363(defun mouse-kill (click)
364 "Kill the region between point and the mouse click.
365The text is saved in the kill ring, as with \\[kill-region]."
ec558adc 366 (interactive "e")
d65147f6 367 (mouse-minibuffer-check click)
142c7672
KH
368 (let* ((posn (event-start click))
369 (click-posn (posn-point posn)))
370 (select-window (posn-window posn))
bd307392
JB
371 (if (numberp click-posn)
372 (kill-region (min (point) click-posn)
373 (max (point) click-posn)))))
72ea54a4 374
87ef29fd
JB
375(defun mouse-yank-at-click (click arg)
376 "Insert the last stretch of killed text at the position clicked on.
50f58001
RS
377Also move point to one end of the text thus inserted (normally the end).
378Prefix arguments are interpreted as with \\[yank].
379If `mouse-yank-at-point' is non-nil, insert at point
380regardless of where you click."
ec558adc 381 (interactive "e\nP")
50f58001 382 (or mouse-yank-at-point (mouse-set-point click))
d89a4a47 383 (setq this-command 'yank)
87ef29fd
JB
384 (yank arg))
385
386(defun mouse-kill-ring-save (click)
cc0a8174
JB
387 "Copy the region between point and the mouse click in the kill ring.
388This does not delete the region; it acts like \\[kill-ring-save]."
ec558adc 389 (interactive "e")
3f26b32a 390 (mouse-set-mark-fast click)
6452d8a6
RS
391 (let (this-command last-command)
392 (kill-ring-save (point) (mark t)))
3f26b32a 393 (mouse-show-mark))
72ea54a4 394
dbc4e1c1
JB
395;;; This function used to delete the text between point and the mouse
396;;; whenever it was equal to the front of the kill ring, but some
397;;; people found that confusing.
398
399;;; A list (TEXT START END), describing the text and position of the last
400;;; invocation of mouse-save-then-kill.
401(defvar mouse-save-then-kill-posn nil)
402
26d280b9 403(defun mouse-save-then-kill-delete-region (beg end)
9a974c88
RS
404 ;; We must make our own undo boundaries
405 ;; because they happen automatically only for the current buffer.
406 (undo-boundary)
dd524dbd
RS
407 (if (or (= beg end) (eq buffer-undo-list t))
408 ;; If we have no undo list in this buffer,
409 ;; just delete.
410 (delete-region beg end)
411 ;; Delete, but make the undo-list entry share with the kill ring.
412 ;; First, delete just one char, so in case buffer is being modified
413 ;; for the first time, the undo list records that fact.
2f4b15ef
RS
414 (let (before-change-function after-change-function
415 before-change-functions after-change-functions)
416 (delete-region beg
417 (+ beg (if (> end beg) 1 -1))))
dd524dbd
RS
418 (let ((buffer-undo-list buffer-undo-list))
419 ;; Undo that deletion--but don't change the undo list!
2f4b15ef
RS
420 (let (before-change-function after-change-function
421 before-change-functions after-change-functions)
422 (primitive-undo 1 buffer-undo-list))
dd524dbd
RS
423 ;; Now delete the rest of the specified region,
424 ;; but don't record it.
425 (setq buffer-undo-list t)
9a974c88
RS
426 (if (/= (length (car kill-ring)) (- (max end beg) (min end beg)))
427 (error "Lossage in mouse-save-then-kill-delete-region"))
dd524dbd
RS
428 (delete-region beg end))
429 (let ((tail buffer-undo-list))
430 ;; Search back in buffer-undo-list for the string
431 ;; that came from deleting one character.
432 (while (and tail (not (stringp (car (car tail)))))
433 (setq tail (cdr tail)))
434 ;; Replace it with an entry for the entire deleted text.
435 (and tail
9a974c88
RS
436 (setcar tail (cons (car kill-ring) (min beg end))))))
437 (undo-boundary))
eb6ff46f 438
947da0c4 439(defun mouse-save-then-kill (click)
40a45a9f
RS
440 "Save text to point in kill ring; the second time, kill the text.
441If the text between point and the mouse is the same as what's
442at the front of the kill ring, this deletes the text.
443Otherwise, it adds the text to the kill ring, like \\[kill-ring-save],
eb6ff46f
RS
444which prepares for a second click to delete the text.
445
446If you have selected words or lines, this command extends the
447selection through the word or line clicked on. If you do this
448again in a different position, it extends the selection again.
449If you do this twice in the same position, the selection is killed."
947da0c4 450 (interactive "e")
d65147f6 451 (mouse-minibuffer-check click)
3f26b32a
RS
452 (let ((click-posn (posn-point (event-start click)))
453 ;; Don't let a subsequent kill command append to this one:
454 ;; prevent setting this-command to kill-region.
455 (this-command this-command))
9a974c88 456 (if (> (mod mouse-selection-click-count 3) 0)
eb6ff46f
RS
457 (if (not (and (eq last-command 'mouse-save-then-kill)
458 (equal click-posn
459 (car (cdr-safe (cdr-safe mouse-save-then-kill-posn))))))
d89a4a47
RS
460 ;; Find both ends of the object selected by this click.
461 (let* ((range
462 (mouse-start-end click-posn click-posn
463 mouse-selection-click-count)))
464 ;; Move whichever end is closer to the click.
465 ;; That's what xterm does, and it seems reasonable.
466 (if (< (abs (- click-posn (mark t)))
467 (abs (- click-posn (point))))
468 (set-mark (car range))
469 (goto-char (nth 1 range)))
eb6ff46f
RS
470 ;; We have already put the old region in the kill ring.
471 ;; Replace it with the extended region.
472 ;; (It would be annoying to make a separate entry.)
473 (setcar kill-ring (buffer-substring (point) (mark t)))
d89a4a47
RS
474 (if interprogram-cut-function
475 (funcall interprogram-cut-function (car kill-ring)))
476 ;; Arrange for a repeated mouse-3 to kill this region.
477 (setq mouse-save-then-kill-posn
478 (list (car kill-ring) (point) click-posn))
eb6ff46f
RS
479 (mouse-show-mark))
480 ;; If we click this button again without moving it,
481 ;; that time kill.
dd524dbd
RS
482 (mouse-save-then-kill-delete-region (point) (mark))
483 (setq mouse-selection-click-count 0)
484 (setq mouse-save-then-kill-posn nil))
eb6ff46f
RS
485 (if (and (eq last-command 'mouse-save-then-kill)
486 mouse-save-then-kill-posn
487 (eq (car mouse-save-then-kill-posn) (car kill-ring))
488 (equal (cdr mouse-save-then-kill-posn) (list (point) click-posn)))
489 ;; If this is the second time we've called
490 ;; mouse-save-then-kill, delete the text from the buffer.
dd524dbd
RS
491 (progn
492 (mouse-save-then-kill-delete-region (point) (mark))
493 ;; After we kill, another click counts as "the first time".
494 (setq mouse-save-then-kill-posn nil))
495 (if (or (and (eq last-command 'mouse-save-then-kill)
496 mouse-save-then-kill-posn)
3544cfc9 497 (and mark-active transient-mark-mode)
d89a4a47 498 (and (eq last-command 'mouse-drag-region)
d89a4a47
RS
499 (or mark-even-if-inactive
500 (not transient-mark-mode))))
501 ;; We have a selection or suitable region, so adjust it.
502 (let* ((posn (event-start click))
503 (new (posn-point posn)))
504 (select-window (posn-window posn))
505 (if (numberp new)
506 (progn
507 ;; Move whichever end of the region is closer to the click.
508 ;; That is what xterm does, and it seems reasonable.
509 (if (< (abs (- new (point))) (abs (- new (mark t))))
510 (goto-char new)
511 (set-mark new))
512 (setq deactivate-mark nil)))
513 (setcar kill-ring (buffer-substring (point) (mark t)))
514 (if interprogram-cut-function
515 (funcall interprogram-cut-function (car kill-ring))))
516 ;; We just have point, so set mark here.
517 (mouse-set-mark-fast click)
518 (kill-ring-save (point) (mark t))
519 (mouse-show-mark))
eb6ff46f
RS
520 (setq mouse-save-then-kill-posn
521 (list (car kill-ring) (point) click-posn))))))
e66feb07
RS
522\f
523(global-set-key [M-mouse-1] 'mouse-start-secondary)
524(global-set-key [M-drag-mouse-1] 'mouse-set-secondary)
525(global-set-key [M-down-mouse-1] 'mouse-drag-secondary)
526(global-set-key [M-mouse-3] 'mouse-secondary-save-then-kill)
9a974c88 527(global-set-key [M-mouse-2] 'mouse-yank-secondary)
e66feb07
RS
528
529;; An overlay which records the current secondary selection
530;; or else is deleted when there is no secondary selection.
531;; May be nil.
532(defvar mouse-secondary-overlay nil)
533
534;; A marker which records the specified first end for a secondary selection.
535;; May be nil.
536(defvar mouse-secondary-start nil)
537
538(defun mouse-start-secondary (click)
539 "Set one end of the secondary selection to the position clicked on.
540Use \\[mouse-secondary-save-then-kill] to set the other end
541and complete the secondary selection."
542 (interactive "e")
d65147f6 543 (mouse-minibuffer-check click)
e66feb07 544 (let ((posn (event-start click)))
230aaa73
RS
545 (save-excursion
546 (set-buffer (window-buffer (posn-window posn)))
547 ;; Cancel any preexisting secondary selection.
548 (if mouse-secondary-overlay
549 (delete-overlay mouse-secondary-overlay))
550 (if (numberp (posn-point posn))
551 (progn
552 (or mouse-secondary-start
553 (setq mouse-secondary-start (make-marker)))
554 (move-marker mouse-secondary-start (posn-point posn)))))))
e66feb07
RS
555
556(defun mouse-set-secondary (click)
557 "Set the secondary selection to the text that the mouse is dragged over.
558This must be bound to a mouse drag event."
559 (interactive "e")
d65147f6 560 (mouse-minibuffer-check click)
e66feb07
RS
561 (let ((posn (event-start click))
562 beg
563 (end (event-end click)))
230aaa73
RS
564 (save-excursion
565 (set-buffer (window-buffer (posn-window posn)))
566 (if (numberp (posn-point posn))
567 (setq beg (posn-point posn)))
568 (if mouse-secondary-overlay
569 (move-overlay mouse-secondary-overlay beg (posn-point end))
570 (setq mouse-secondary-overlay (make-overlay beg (posn-point end))))
571 (overlay-put mouse-secondary-overlay 'face 'secondary-selection))))
947da0c4 572
d89a4a47 573(defun mouse-drag-secondary (start-event)
e66feb07 574 "Set the secondary selection to the text that the mouse is dragged over.
d89a4a47 575Highlight the drag area as you move the mouse.
e66feb07
RS
576This must be bound to a button-down mouse event."
577 (interactive "e")
d65147f6 578 (mouse-minibuffer-check start-event)
d89a4a47
RS
579 (let* ((start-posn (event-start start-event))
580 (start-point (posn-point start-posn))
581 (start-window (posn-window start-posn))
582 (start-frame (window-frame start-window))
583 (bounds (window-edges start-window))
584 (top (nth 1 bounds))
585 (bottom (if (window-minibuffer-p start-window)
586 (nth 3 bounds)
587 ;; Don't count the mode line.
588 (1- (nth 3 bounds))))
589 (click-count (1- (event-click-count start-event))))
590 (save-excursion
591 (set-buffer (window-buffer start-window))
592 (setq mouse-selection-click-count click-count)
d89a4a47
RS
593 (or mouse-secondary-overlay
594 (setq mouse-secondary-overlay
595 (make-overlay (point) (point))))
26d280b9 596 (overlay-put mouse-secondary-overlay 'face 'secondary-selection)
9a974c88 597 (if (> (mod click-count 3) 0)
26d280b9
RS
598 ;; Double or triple press: make an initial selection
599 ;; of one word or line.
d89a4a47
RS
600 (let ((range (mouse-start-end start-point start-point click-count)))
601 (set-marker mouse-secondary-start nil)
602 (move-overlay mouse-secondary-overlay 1 1
603 (window-buffer start-window))
604 (move-overlay mouse-secondary-overlay (car range) (nth 1 range)
605 (window-buffer start-window)))
26d280b9 606 ;; Single-press: cancel any preexisting secondary selection.
d89a4a47
RS
607 (or mouse-secondary-start
608 (setq mouse-secondary-start (make-marker)))
609 (set-marker mouse-secondary-start start-point)
610 (delete-overlay mouse-secondary-overlay))
611 (let (event end end-point)
612 (track-mouse
613 (while (progn
614 (setq event (read-event))
615 (or (mouse-movement-p event)
616 (eq (car-safe event) 'switch-frame)))
617
618 (if (eq (car-safe event) 'switch-frame)
619 nil
620 (setq end (event-end event)
621 end-point (posn-point end))
622 (cond
d89a4a47
RS
623 ;; Are we moving within the original window?
624 ((and (eq (posn-window end) start-window)
625 (integer-or-marker-p end-point))
d89a4a47
RS
626 (let ((range (mouse-start-end start-point end-point
627 click-count)))
0136e1e3
RS
628 (if (or (/= start-point end-point)
629 (null (marker-position mouse-secondary-start)))
630 (progn
631 (set-marker mouse-secondary-start nil)
632 (move-overlay mouse-secondary-overlay
633 (car range) (nth 1 range))))))
3b0aebe9
RS
634 (t
635 (let ((mouse-row (cdr (cdr (mouse-position)))))
636 (cond
637 ((null mouse-row))
638 ((< mouse-row top)
e919a622
RS
639 (mouse-scroll-subr start-window (- mouse-row top)
640 mouse-secondary-overlay start-point))
d2287ded 641 ((>= mouse-row bottom)
e919a622 642 (mouse-scroll-subr start-window (1+ (- mouse-row bottom))
3b0aebe9 643 mouse-secondary-overlay start-point)))))))))
d89a4a47 644
4e399a53
RS
645 (if (consp event)
646;;; (eq (get (event-basic-type event) 'event-kind) 'mouse-click)
647;;; (eq (posn-window (event-end event)) start-window)
648;;; (numberp (posn-point (event-end event)))
d89a4a47
RS
649 (if (marker-position mouse-secondary-start)
650 (save-window-excursion
651 (delete-overlay mouse-secondary-overlay)
9a974c88 652 (x-set-selection 'SECONDARY nil)
d89a4a47
RS
653 (select-window start-window)
654 (save-excursion
655 (goto-char mouse-secondary-start)
656 (sit-for 1)))
9a974c88
RS
657 (x-set-selection
658 'SECONDARY
659 (buffer-substring (overlay-start mouse-secondary-overlay)
660 (overlay-end mouse-secondary-overlay)))))))))
e66feb07 661
9a974c88 662(defun mouse-yank-secondary (click)
50f58001
RS
663 "Insert the secondary selection at the position clicked on.
664Move point to the end of the inserted text.
665If `mouse-yank-at-point' is non-nil, insert at point
666regardless of where you click."
9a974c88 667 (interactive "e")
50f58001
RS
668 (or mouse-yank-at-point (mouse-set-point click))
669 (insert (x-get-selection 'SECONDARY)))
9a974c88 670
7e6404f6 671(defun mouse-kill-secondary ()
9a974c88
RS
672 "Kill the text in the secondary selection.
673This is intended more as a keyboard command than as a mouse command
674but it can work as either one.
675
676The current buffer (in case of keyboard use), or the buffer clicked on,
677must be the one that the secondary selection is in. This requirement
678is to prevent accidents."
7e6404f6
RS
679 (interactive)
680 (let* ((keys (this-command-keys))
681 (click (elt keys (1- (length keys)))))
682 (or (eq (overlay-buffer mouse-secondary-overlay)
683 (if (listp click)
684 (window-buffer (posn-window (event-start click)))
685 (current-buffer)))
686 (error "Select or click on the buffer where the secondary selection is")))
9a974c88
RS
687 (save-excursion
688 (set-buffer (overlay-buffer mouse-secondary-overlay))
689 (kill-region (overlay-start mouse-secondary-overlay)
690 (overlay-end mouse-secondary-overlay)))
e66feb07 691 (delete-overlay mouse-secondary-overlay)
9a974c88 692 (x-set-selection 'SECONDARY nil)
e66feb07
RS
693 (setq mouse-secondary-overlay nil))
694
695(defun mouse-secondary-save-then-kill (click)
d89a4a47 696 "Save text to point in kill ring; the second time, kill the text.
7bbe2cc7
RS
697You must use this in a buffer where you have recently done \\[mouse-start-secondary].
698If the text between where you did \\[mouse-start-secondary] and where
699you use this command matches the text at the front of the kill ring,
700this command deletes the text.
e66feb07 701Otherwise, it adds the text to the kill ring, like \\[kill-ring-save],
7bbe2cc7 702which prepares for a second click with this command to delete the text.
d89a4a47 703
7bbe2cc7
RS
704If you have already made a secondary selection in that buffer,
705this command extends or retracts the selection to where you click.
706If you do this again in a different position, it extends or retracts
707again. If you do this twice in the same position, it kills the selection."
e66feb07 708 (interactive "e")
d65147f6 709 (mouse-minibuffer-check click)
d89a4a47
RS
710 (let ((posn (event-start click))
711 (click-posn (posn-point (event-start click)))
e66feb07
RS
712 ;; Don't let a subsequent kill command append to this one:
713 ;; prevent setting this-command to kill-region.
714 (this-command this-command))
9a974c88
RS
715 (or (eq (window-buffer (posn-window posn))
716 (or (and mouse-secondary-overlay
717 (overlay-buffer mouse-secondary-overlay))
718 (if mouse-secondary-start
719 (marker-buffer mouse-secondary-start))))
720 (error "Wrong buffer"))
721 (save-excursion
722 (set-buffer (window-buffer (posn-window posn)))
723 (if (> (mod mouse-selection-click-count 3) 0)
724 (if (not (and (eq last-command 'mouse-secondary-save-then-kill)
725 (equal click-posn
726 (car (cdr-safe (cdr-safe mouse-save-then-kill-posn))))))
727 ;; Find both ends of the object selected by this click.
728 (let* ((range
729 (mouse-start-end click-posn click-posn
730 mouse-selection-click-count)))
731 ;; Move whichever end is closer to the click.
732 ;; That's what xterm does, and it seems reasonable.
733 (if (< (abs (- click-posn (overlay-start mouse-secondary-overlay)))
734 (abs (- click-posn (overlay-end mouse-secondary-overlay))))
735 (move-overlay mouse-secondary-overlay (car range)
736 (overlay-end mouse-secondary-overlay))
d89a4a47
RS
737 (move-overlay mouse-secondary-overlay
738 (overlay-start mouse-secondary-overlay)
739 (nth 1 range)))
9a974c88
RS
740 ;; We have already put the old region in the kill ring.
741 ;; Replace it with the extended region.
742 ;; (It would be annoying to make a separate entry.)
743 (setcar kill-ring (buffer-substring
744 (overlay-start mouse-secondary-overlay)
745 (overlay-end mouse-secondary-overlay)))
746 (if interprogram-cut-function
747 (funcall interprogram-cut-function (car kill-ring)))
748 ;; Arrange for a repeated mouse-3 to kill this region.
749 (setq mouse-save-then-kill-posn
750 (list (car kill-ring) (point) click-posn)))
751 ;; If we click this button again without moving it,
752 ;; that time kill.
d89a4a47 753 (progn
9a974c88
RS
754 (mouse-save-then-kill-delete-region
755 (overlay-start mouse-secondary-overlay)
756 (overlay-end mouse-secondary-overlay))
757 (setq mouse-save-then-kill-posn nil)
758 (setq mouse-selection-click-count 0)
759 (delete-overlay mouse-secondary-overlay)))
760 (if (and (eq last-command 'mouse-secondary-save-then-kill)
761 mouse-save-then-kill-posn
762 (eq (car mouse-save-then-kill-posn) (car kill-ring))
763 (equal (cdr mouse-save-then-kill-posn) (list (point) click-posn)))
764 ;; If this is the second time we've called
765 ;; mouse-secondary-save-then-kill, delete the text from the buffer.
766 (progn
767 (mouse-save-then-kill-delete-region
768 (overlay-start mouse-secondary-overlay)
769 (overlay-end mouse-secondary-overlay))
770 (setq mouse-save-then-kill-posn nil)
771 (delete-overlay mouse-secondary-overlay))
772 (if (overlay-start mouse-secondary-overlay)
773 ;; We have a selection, so adjust it.
774 (progn
775 (if (numberp click-posn)
776 (progn
777 ;; Move whichever end of the region is closer to the click.
778 ;; That is what xterm does, and it seems reasonable.
779 (if (< (abs (- click-posn (overlay-start mouse-secondary-overlay)))
780 (abs (- click-posn (overlay-end mouse-secondary-overlay))))
781 (move-overlay mouse-secondary-overlay click-posn
782 (overlay-end mouse-secondary-overlay))
d89a4a47
RS
783 (move-overlay mouse-secondary-overlay
784 (overlay-start mouse-secondary-overlay)
785 click-posn))
9a974c88 786 (setq deactivate-mark nil)))
0136e1e3
RS
787 (if (eq last-command 'mouse-secondary-save-then-kill)
788 (progn
789 ;; If the front of the kill ring comes from
790 ;; an immediately previous use of this command,
791 ;; replace it with the extended region.
792 ;; (It would be annoying to make a separate entry.)
793 (setcar kill-ring
794 (buffer-substring
795 (overlay-start mouse-secondary-overlay)
796 (overlay-end mouse-secondary-overlay)))
797 (if interprogram-cut-function
798 (funcall interprogram-cut-function (car kill-ring))))
799 (copy-region-as-kill (overlay-start mouse-secondary-overlay)
800 (overlay-end mouse-secondary-overlay))))
9a974c88
RS
801 (if mouse-secondary-start
802 ;; All we have is one end of a selection,
803 ;; so put the other end here.
804 (let ((start (+ 0 mouse-secondary-start)))
805 (kill-ring-save start click-posn)
806 (if mouse-secondary-overlay
807 (move-overlay mouse-secondary-overlay start click-posn)
808 (setq mouse-secondary-overlay (make-overlay start click-posn)))
809 (overlay-put mouse-secondary-overlay 'face 'secondary-selection))))
810 (setq mouse-save-then-kill-posn
811 (list (car kill-ring) (point) click-posn))))
812 (x-set-selection 'SECONDARY
813 (if (overlay-buffer mouse-secondary-overlay)
814 (buffer-substring
815 (overlay-start mouse-secondary-overlay)
816 (overlay-end mouse-secondary-overlay)))))))
e66feb07 817\f
8b34e79d 818(defun mouse-buffer-menu (event)
2d82f7b9
RS
819 "Pop up a menu of buffers for selection with the mouse.
820This switches buffers in the window that you clicked on,
821and selects that window."
ec558adc 822 (interactive "e")
d65147f6 823 (mouse-minibuffer-check event)
8b34e79d
RS
824 (let ((menu
825 (list "Buffer Menu"
826 (cons "Select Buffer"
827 (let ((tail (buffer-list))
af2a85fe 828 (maxbuf 0)
8b34e79d 829 head)
af2a85fe
RS
830 (while tail
831 (or (eq ?\ (aref (buffer-name (car tail)) 0))
832 (setq maxbuf
833 (max maxbuf
834 (length (buffer-name (car tail))))))
835 (setq tail (cdr tail)))
836 (setq tail (buffer-list))
8b34e79d
RS
837 (while tail
838 (let ((elt (car tail)))
839 (if (not (string-match "^ "
840 (buffer-name elt)))
841 (setq head (cons
842 (cons
843 (format
af2a85fe
RS
844 (format "%%%ds %%s%%s %%s"
845 maxbuf)
8b34e79d 846 (buffer-name elt)
af2a85fe
RS
847 (if (buffer-modified-p elt)
848 "*" " ")
849 (save-excursion
850 (set-buffer elt)
851 (if buffer-read-only "%" " "))
8b34e79d
RS
852 (or (buffer-file-name elt) ""))
853 elt)
854 head))))
855 (setq tail (cdr tail)))
856 (reverse head))))))
2d82f7b9
RS
857 (let ((buf (x-popup-menu event menu))
858 (window (posn-window (event-start event))))
859 (if buf
860 (progn
c0bb9f3b 861 (or (framep window) (select-window window))
2d82f7b9 862 (switch-to-buffer buf))))))
72ea54a4 863\f
5ba2dc3f 864;;; These need to be rewritten for the new scroll bar implementation.
dbc4e1c1
JB
865
866;;;!! ;; Commands for the scroll bar.
867;;;!!
868;;;!! (defun mouse-scroll-down (click)
869;;;!! (interactive "@e")
870;;;!! (scroll-down (1+ (cdr (mouse-coords click)))))
871;;;!!
872;;;!! (defun mouse-scroll-up (click)
873;;;!! (interactive "@e")
874;;;!! (scroll-up (1+ (cdr (mouse-coords click)))))
875;;;!!
876;;;!! (defun mouse-scroll-down-full ()
877;;;!! (interactive "@")
878;;;!! (scroll-down nil))
879;;;!!
880;;;!! (defun mouse-scroll-up-full ()
881;;;!! (interactive "@")
882;;;!! (scroll-up nil))
883;;;!!
884;;;!! (defun mouse-scroll-move-cursor (click)
885;;;!! (interactive "@e")
886;;;!! (move-to-window-line (1+ (cdr (mouse-coords click)))))
887;;;!!
888;;;!! (defun mouse-scroll-absolute (event)
889;;;!! (interactive "@e")
890;;;!! (let* ((pos (car event))
891;;;!! (position (car pos))
892;;;!! (length (car (cdr pos))))
893;;;!! (if (<= length 0) (setq length 1))
894;;;!! (let* ((scale-factor (max 1 (/ length (/ 8000000 (buffer-size)))))
895;;;!! (newpos (* (/ (* (/ (buffer-size) scale-factor)
896;;;!! position)
897;;;!! length)
898;;;!! scale-factor)))
899;;;!! (goto-char newpos)
900;;;!! (recenter '(4)))))
901;;;!!
902;;;!! (defun mouse-scroll-left (click)
903;;;!! (interactive "@e")
904;;;!! (scroll-left (1+ (car (mouse-coords click)))))
905;;;!!
906;;;!! (defun mouse-scroll-right (click)
907;;;!! (interactive "@e")
908;;;!! (scroll-right (1+ (car (mouse-coords click)))))
909;;;!!
910;;;!! (defun mouse-scroll-left-full ()
911;;;!! (interactive "@")
912;;;!! (scroll-left nil))
913;;;!!
914;;;!! (defun mouse-scroll-right-full ()
915;;;!! (interactive "@")
916;;;!! (scroll-right nil))
917;;;!!
918;;;!! (defun mouse-scroll-move-cursor-horizontally (click)
919;;;!! (interactive "@e")
920;;;!! (move-to-column (1+ (car (mouse-coords click)))))
921;;;!!
922;;;!! (defun mouse-scroll-absolute-horizontally (event)
923;;;!! (interactive "@e")
924;;;!! (let* ((pos (car event))
925;;;!! (position (car pos))
926;;;!! (length (car (cdr pos))))
927;;;!! (set-window-hscroll (selected-window) 33)))
928;;;!!
929;;;!! (global-set-key [scroll-bar mouse-1] 'mouse-scroll-up)
930;;;!! (global-set-key [scroll-bar mouse-2] 'mouse-scroll-absolute)
931;;;!! (global-set-key [scroll-bar mouse-3] 'mouse-scroll-down)
932;;;!!
933;;;!! (global-set-key [vertical-slider mouse-1] 'mouse-scroll-move-cursor)
934;;;!! (global-set-key [vertical-slider mouse-2] 'mouse-scroll-move-cursor)
935;;;!! (global-set-key [vertical-slider mouse-3] 'mouse-scroll-move-cursor)
936;;;!!
937;;;!! (global-set-key [thumbup mouse-1] 'mouse-scroll-up-full)
938;;;!! (global-set-key [thumbup mouse-2] 'mouse-scroll-up-full)
939;;;!! (global-set-key [thumbup mouse-3] 'mouse-scroll-up-full)
940;;;!!
941;;;!! (global-set-key [thumbdown mouse-1] 'mouse-scroll-down-full)
942;;;!! (global-set-key [thumbdown mouse-2] 'mouse-scroll-down-full)
943;;;!! (global-set-key [thumbdown mouse-3] 'mouse-scroll-down-full)
944;;;!!
945;;;!! (global-set-key [horizontal-scroll-bar mouse-1] 'mouse-scroll-left)
946;;;!! (global-set-key [horizontal-scroll-bar mouse-2]
947;;;!! 'mouse-scroll-absolute-horizontally)
948;;;!! (global-set-key [horizontal-scroll-bar mouse-3] 'mouse-scroll-right)
949;;;!!
950;;;!! (global-set-key [horizontal-slider mouse-1]
951;;;!! 'mouse-scroll-move-cursor-horizontally)
952;;;!! (global-set-key [horizontal-slider mouse-2]
953;;;!! 'mouse-scroll-move-cursor-horizontally)
954;;;!! (global-set-key [horizontal-slider mouse-3]
955;;;!! 'mouse-scroll-move-cursor-horizontally)
956;;;!!
957;;;!! (global-set-key [thumbleft mouse-1] 'mouse-scroll-left-full)
958;;;!! (global-set-key [thumbleft mouse-2] 'mouse-scroll-left-full)
959;;;!! (global-set-key [thumbleft mouse-3] 'mouse-scroll-left-full)
960;;;!!
961;;;!! (global-set-key [thumbright mouse-1] 'mouse-scroll-right-full)
962;;;!! (global-set-key [thumbright mouse-2] 'mouse-scroll-right-full)
963;;;!! (global-set-key [thumbright mouse-3] 'mouse-scroll-right-full)
964;;;!!
965;;;!! (global-set-key [horizontal-scroll-bar S-mouse-2]
966;;;!! 'mouse-split-window-horizontally)
967;;;!! (global-set-key [mode-line S-mouse-2]
968;;;!! 'mouse-split-window-horizontally)
969;;;!! (global-set-key [vertical-scroll-bar S-mouse-2]
970;;;!! 'mouse-split-window)
6b2154de 971\f
dbc4e1c1
JB
972;;;!! ;;;;
973;;;!! ;;;; Here are experimental things being tested. Mouse events
974;;;!! ;;;; are of the form:
975;;;!! ;;;; ((x y) window screen-part key-sequence timestamp)
976;;;!! ;;
977;;;!! ;;;;
978;;;!! ;;;; Dynamically track mouse coordinates
979;;;!! ;;;;
980;;;!! ;;
981;;;!! ;;(defun track-mouse (event)
982;;;!! ;; "Track the coordinates, absolute and relative, of the mouse."
983;;;!! ;; (interactive "@e")
984;;;!! ;; (while mouse-grabbed
985;;;!! ;; (let* ((pos (read-mouse-position (selected-screen)))
986;;;!! ;; (abs-x (car pos))
987;;;!! ;; (abs-y (cdr pos))
988;;;!! ;; (relative-coordinate (coordinates-in-window-p
989;;;!! ;; (list (car pos) (cdr pos))
990;;;!! ;; (selected-window))))
991;;;!! ;; (if (consp relative-coordinate)
992;;;!! ;; (message "mouse: [%d %d], (%d %d)" abs-x abs-y
993;;;!! ;; (car relative-coordinate)
994;;;!! ;; (car (cdr relative-coordinate)))
995;;;!! ;; (message "mouse: [%d %d]" abs-x abs-y)))))
996;;;!!
997;;;!! ;;
998;;;!! ;; Dynamically put a box around the line indicated by point
999;;;!! ;;
1000;;;!! ;;
1001;;;!! ;;(require 'backquote)
1002;;;!! ;;
1003;;;!! ;;(defun mouse-select-buffer-line (event)
1004;;;!! ;; (interactive "@e")
1005;;;!! ;; (let ((relative-coordinate
1006;;;!! ;; (coordinates-in-window-p (car event) (selected-window)))
1007;;;!! ;; (abs-y (car (cdr (car event)))))
1008;;;!! ;; (if (consp relative-coordinate)
1009;;;!! ;; (progn
1010;;;!! ;; (save-excursion
1011;;;!! ;; (move-to-window-line (car (cdr relative-coordinate)))
1012;;;!! ;; (x-draw-rectangle
1013;;;!! ;; (selected-screen)
1014;;;!! ;; abs-y 0
1015;;;!! ;; (save-excursion
1016;;;!! ;; (move-to-window-line (car (cdr relative-coordinate)))
1017;;;!! ;; (end-of-line)
1018;;;!! ;; (push-mark nil t)
1019;;;!! ;; (beginning-of-line)
1020;;;!! ;; (- (region-end) (region-beginning))) 1))
1021;;;!! ;; (sit-for 1)
1022;;;!! ;; (x-erase-rectangle (selected-screen))))))
1023;;;!! ;;
1024;;;!! ;;(defvar last-line-drawn nil)
1025;;;!! ;;(defvar begin-delim "[^ \t]")
1026;;;!! ;;(defvar end-delim "[^ \t]")
1027;;;!! ;;
1028;;;!! ;;(defun mouse-boxing (event)
1029;;;!! ;; (interactive "@e")
1030;;;!! ;; (save-excursion
1031;;;!! ;; (let ((screen (selected-screen)))
1032;;;!! ;; (while (= (x-mouse-events) 0)
1033;;;!! ;; (let* ((pos (read-mouse-position screen))
1034;;;!! ;; (abs-x (car pos))
1035;;;!! ;; (abs-y (cdr pos))
1036;;;!! ;; (relative-coordinate
1037;;;!! ;; (coordinates-in-window-p (` ((, abs-x) (, abs-y)))
1038;;;!! ;; (selected-window)))
1039;;;!! ;; (begin-reg nil)
1040;;;!! ;; (end-reg nil)
1041;;;!! ;; (end-column nil)
1042;;;!! ;; (begin-column nil))
1043;;;!! ;; (if (and (consp relative-coordinate)
1044;;;!! ;; (or (not last-line-drawn)
1045;;;!! ;; (not (= last-line-drawn abs-y))))
1046;;;!! ;; (progn
1047;;;!! ;; (move-to-window-line (car (cdr relative-coordinate)))
1048;;;!! ;; (if (= (following-char) 10)
1049;;;!! ;; ()
1050;;;!! ;; (progn
1051;;;!! ;; (setq begin-reg (1- (re-search-forward end-delim)))
1052;;;!! ;; (setq begin-column (1- (current-column)))
1053;;;!! ;; (end-of-line)
1054;;;!! ;; (setq end-reg (1+ (re-search-backward begin-delim)))
1055;;;!! ;; (setq end-column (1+ (current-column)))
1056;;;!! ;; (message "%s" (buffer-substring begin-reg end-reg))
1057;;;!! ;; (x-draw-rectangle screen
1058;;;!! ;; (setq last-line-drawn abs-y)
1059;;;!! ;; begin-column
1060;;;!! ;; (- end-column begin-column) 1))))))))))
1061;;;!! ;;
1062;;;!! ;;(defun mouse-erase-box ()
1063;;;!! ;; (interactive)
1064;;;!! ;; (if last-line-drawn
1065;;;!! ;; (progn
1066;;;!! ;; (x-erase-rectangle (selected-screen))
1067;;;!! ;; (setq last-line-drawn nil))))
1068;;;!!
1069;;;!! ;;; (defun test-x-rectangle ()
1070;;;!! ;;; (use-local-mouse-map (setq rectangle-test-map (make-sparse-keymap)))
1071;;;!! ;;; (define-key rectangle-test-map mouse-motion-button-left 'mouse-boxing)
1072;;;!! ;;; (define-key rectangle-test-map mouse-button-left-up 'mouse-erase-box))
1073;;;!!
1074;;;!! ;;
1075;;;!! ;; Here is how to do double clicking in lisp. About to change.
1076;;;!! ;;
1077;;;!!
1078;;;!! (defvar double-start nil)
1079;;;!! (defconst double-click-interval 300
1080;;;!! "Max ticks between clicks")
1081;;;!!
1082;;;!! (defun double-down (event)
1083;;;!! (interactive "@e")
1084;;;!! (if double-start
1085;;;!! (let ((interval (- (nth 4 event) double-start)))
1086;;;!! (if (< interval double-click-interval)
1087;;;!! (progn
1088;;;!! (backward-up-list 1)
1089;;;!! ;; (message "Interval %d" interval)
1090;;;!! (sleep-for 1)))
1091;;;!! (setq double-start nil))
1092;;;!! (setq double-start (nth 4 event))))
1093;;;!!
1094;;;!! (defun double-up (event)
1095;;;!! (interactive "@e")
1096;;;!! (and double-start
1097;;;!! (> (- (nth 4 event ) double-start) double-click-interval)
1098;;;!! (setq double-start nil)))
1099;;;!!
1100;;;!! ;;; (defun x-test-doubleclick ()
1101;;;!! ;;; (use-local-mouse-map (setq doubleclick-test-map (make-sparse-keymap)))
1102;;;!! ;;; (define-key doubleclick-test-map mouse-button-left 'double-down)
1103;;;!! ;;; (define-key doubleclick-test-map mouse-button-left-up 'double-up))
1104;;;!!
1105;;;!! ;;
5ba2dc3f 1106;;;!! ;; This scrolls while button is depressed. Use preferable in scroll bar.
dbc4e1c1
JB
1107;;;!! ;;
1108;;;!!
1109;;;!! (defvar scrolled-lines 0)
1110;;;!! (defconst scroll-speed 1)
1111;;;!!
1112;;;!! (defun incr-scroll-down (event)
1113;;;!! (interactive "@e")
1114;;;!! (setq scrolled-lines 0)
1115;;;!! (incremental-scroll scroll-speed))
1116;;;!!
1117;;;!! (defun incr-scroll-up (event)
1118;;;!! (interactive "@e")
1119;;;!! (setq scrolled-lines 0)
1120;;;!! (incremental-scroll (- scroll-speed)))
1121;;;!!
1122;;;!! (defun incremental-scroll (n)
1123;;;!! (while (= (x-mouse-events) 0)
1124;;;!! (setq scrolled-lines (1+ (* scroll-speed scrolled-lines)))
1125;;;!! (scroll-down n)
1126;;;!! (sit-for 300 t)))
1127;;;!!
1128;;;!! (defun incr-scroll-stop (event)
1129;;;!! (interactive "@e")
1130;;;!! (message "Scrolled %d lines" scrolled-lines)
1131;;;!! (setq scrolled-lines 0)
1132;;;!! (sleep-for 1))
1133;;;!!
1134;;;!! ;;; (defun x-testing-scroll ()
1135;;;!! ;;; (let ((scrolling-map (function mouse-vertical-scroll-bar-prefix)))
1136;;;!! ;;; (define-key scrolling-map mouse-button-left 'incr-scroll-down)
1137;;;!! ;;; (define-key scrolling-map mouse-button-right 'incr-scroll-up)
1138;;;!! ;;; (define-key scrolling-map mouse-button-left-up 'incr-scroll-stop)
1139;;;!! ;;; (define-key scrolling-map mouse-button-right-up 'incr-scroll-stop)))
1140;;;!!
1141;;;!! ;;
1142;;;!! ;; Some playthings suitable for picture mode? They need work.
1143;;;!! ;;
1144;;;!!
1145;;;!! (defun mouse-kill-rectangle (event)
1146;;;!! "Kill the rectangle between point and the mouse cursor."
1147;;;!! (interactive "@e")
1148;;;!! (let ((point-save (point)))
1149;;;!! (save-excursion
1150;;;!! (mouse-set-point event)
1151;;;!! (push-mark nil t)
1152;;;!! (if (> point-save (point))
1153;;;!! (kill-rectangle (point) point-save)
1154;;;!! (kill-rectangle point-save (point))))))
1155;;;!!
1156;;;!! (defun mouse-open-rectangle (event)
1157;;;!! "Kill the rectangle between point and the mouse cursor."
1158;;;!! (interactive "@e")
1159;;;!! (let ((point-save (point)))
1160;;;!! (save-excursion
1161;;;!! (mouse-set-point event)
1162;;;!! (push-mark nil t)
1163;;;!! (if (> point-save (point))
1164;;;!! (open-rectangle (point) point-save)
1165;;;!! (open-rectangle point-save (point))))))
1166;;;!!
1167;;;!! ;; Must be a better way to do this.
1168;;;!!
1169;;;!! (defun mouse-multiple-insert (n char)
1170;;;!! (while (> n 0)
1171;;;!! (insert char)
1172;;;!! (setq n (1- n))))
1173;;;!!
1174;;;!! ;; What this could do is not finalize until button was released.
1175;;;!!
1176;;;!! (defun mouse-move-text (event)
1177;;;!! "Move text from point to cursor position, inserting spaces."
1178;;;!! (interactive "@e")
1179;;;!! (let* ((relative-coordinate
1180;;;!! (coordinates-in-window-p (car event) (selected-window))))
1181;;;!! (if (consp relative-coordinate)
1182;;;!! (cond ((> (current-column) (car relative-coordinate))
1183;;;!! (delete-char
1184;;;!! (- (car relative-coordinate) (current-column))))
1185;;;!! ((< (current-column) (car relative-coordinate))
1186;;;!! (mouse-multiple-insert
1187;;;!! (- (car relative-coordinate) (current-column)) " "))
1188;;;!! ((= (current-column) (car relative-coordinate)) (ding))))))
07a78410 1189\f
f936ae06
RS
1190;; Choose a completion with the mouse.
1191
1192(defun mouse-choose-completion (event)
49e61c42 1193 "Click on an alternative in the `*Completions*' buffer to choose it."
f936ae06 1194 (interactive "e")
d89a4a47 1195 (let ((buffer (window-buffer))
02680e9b
RS
1196 choice
1197 base-size)
f936ae06
RS
1198 (save-excursion
1199 (set-buffer (window-buffer (posn-window (event-start event))))
f36f4e9e
RS
1200 (if completion-reference-buffer
1201 (setq buffer completion-reference-buffer))
02680e9b 1202 (setq base-size completion-base-size)
f936ae06
RS
1203 (save-excursion
1204 (goto-char (posn-point (event-start event)))
b6be5d95 1205 (let (beg end)
9a43a594
RS
1206 (if (and (not (eobp)) (get-text-property (point) 'mouse-face))
1207 (setq end (point) beg (1+ (point))))
1208 (if (null beg)
1209 (error "No completion here"))
1210 (setq beg (previous-single-property-change beg 'mouse-face))
2f5ed2e8
RS
1211 (setq end (or (next-single-property-change end 'mouse-face)
1212 (point-max)))
b6be5d95 1213 (setq choice (buffer-substring beg end)))))
73e2025f
RS
1214 (let ((owindow (selected-window)))
1215 (select-window (posn-window (event-start event)))
874a2cbd
RS
1216 (if (and (one-window-p t 'selected-frame)
1217 (window-dedicated-p (selected-window)))
1218 ;; This is a special buffer's frame
1219 (iconify-frame (selected-frame))
1220 (or (window-dedicated-p (selected-window))
1221 (bury-buffer)))
73e2025f 1222 (select-window owindow))
02680e9b 1223 (choose-completion-string choice buffer base-size)))
f936ae06 1224\f
07a78410
RS
1225;; Font selection.
1226
0eb9fef3
RS
1227(defun font-menu-add-default ()
1228 (let* ((default (cdr (assq 'font (frame-parameters (selected-frame)))))
1229 (font-alist x-fixed-font-alist)
0d94f5ca 1230 (elt (or (assoc "Misc" font-alist) (nth 1 font-alist))))
0eb9fef3
RS
1231 (if (assoc "Default" elt)
1232 (delete (assoc "Default" elt) elt))
1233 (setcdr elt
3d64d15b 1234 (cons (list "Default"
0eb9fef3
RS
1235 (cdr (assq 'font (frame-parameters (selected-frame)))))
1236 (cdr elt)))))
1237
07a78410
RS
1238(defvar x-fixed-font-alist
1239 '("Font menu"
1240 ("Misc"
19d973e8
RS
1241 ;; For these, we specify the pixel height and width.
1242 ("fixed" "fixed")
1243 ("6x10" "-misc-fixed-medium-r-normal--10-*-*-*-c-60-iso8859-1" "6x10")
1244 ("6x12"
1245 "-misc-fixed-medium-r-semicondensed--12-*-*-*-c-60-iso8859-1" "6x12")
1246 ("6x13"
1247 "-misc-fixed-medium-r-semicondensed--13-*-*-*-c-60-iso8859-1" "6x13")
1248 ("7x13" "-misc-fixed-medium-r-normal--13-*-*-*-c-70-iso8859-1" "7x13")
1249 ("7x14" "-misc-fixed-medium-r-normal--14-*-*-*-c-70-iso8859-1" "7x14")
1250 ("8x13" "-misc-fixed-medium-r-normal--13-*-*-*-c-80-iso8859-1" "8x13")
1251 ("9x15" "-misc-fixed-medium-r-normal--15-*-*-*-c-90-iso8859-1" "9x15")
1252 ("10x20" "-misc-fixed-medium-r-normal--20-*-*-*-c-100-iso8859-1" "10x20")
1253 ("11x18" "-misc-fixed-medium-r-normal--18-*-*-*-c-110-iso8859-1" "11x18")
1254 ("12x24" "-misc-fixed-medium-r-normal--24-*-*-*-c-120-iso8859-1" "12x24")
fa21fdec 1255 ("")
19d973e8
RS
1256 ("clean 8x8"
1257 "-schumacher-clean-medium-r-normal--8-*-*-*-c-80-iso8859-1")
1258 ("clean 8x10"
1259 "-schumacher-clean-medium-r-normal--10-*-*-*-c-80-iso8859-1")
1260 ("clean 8x14"
1261 "-schumacher-clean-medium-r-normal--14-*-*-*-c-80-iso8859-1")
1262 ("clean 8x16"
1263 "-schumacher-clean-medium-r-normal--16-*-*-*-c-80-iso8859-1")
fa21fdec 1264 ("")
19d973e8 1265 ("sony 8x16" "-sony-fixed-medium-r-normal--16-*-*-*-c-80-iso8859-1"))
07a78410
RS
1266;;; We don't seem to have these; who knows what they are.
1267;;; ("fg-18" "fg-18")
1268;;; ("fg-25" "fg-25")
1269;;; ("lucidasanstypewriter-12" "lucidasanstypewriter-12")
1270;;; ("lucidasanstypewriter-bold-14" "lucidasanstypewriter-bold-14")
1271;;; ("lucidasanstypewriter-bold-24" "lucidasanstypewriter-bold-24")
1272;;; ("lucidatypewriter-bold-r-24" "-b&h-lucidatypewriter-bold-r-normal-sans-24-240-75-75-m-140-iso8859-1")
1273;;; ("fixed-medium-20" "-misc-fixed-medium-*-*-*-20-*-*-*-*-*-*-*")
1274 ("Courier"
19d973e8 1275 ;; For these, we specify the point height.
82c048a9
RS
1276 ("8" "-adobe-courier-medium-r-normal--*-80-*-*-m-*-iso8859-1")
1277 ("10" "-adobe-courier-medium-r-normal--*-100-*-*-m-*-iso8859-1")
1278 ("12" "-adobe-courier-medium-r-normal--*-120-*-*-m-*-iso8859-1")
1279 ("14" "-adobe-courier-medium-r-normal--*-140-*-*-m-*-iso8859-1")
1280 ("18" "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1")
1281 ("24" "-adobe-courier-medium-r-normal--*-240-*-*-m-*-iso8859-1")
1282 ("8 bold" "-adobe-courier-bold-r-normal--*-80-*-*-m-*-iso8859-1")
1283 ("10 bold" "-adobe-courier-bold-r-normal--*-100-*-*-m-*-iso8859-1")
1284 ("12 bold" "-adobe-courier-bold-r-normal--*-120-*-*-m-*-iso8859-1")
1285 ("14 bold" "-adobe-courier-bold-r-normal--*-140-*-*-m-*-iso8859-1")
1286 ("18 bold" "-adobe-courier-bold-r-normal--*-180-*-*-m-*-iso8859-1")
1287 ("24 bold" "-adobe-courier-bold-r-normal--*-240-*-*-m-*-iso8859-1")
1288 ("8 slant" "-adobe-courier-medium-o-normal--*-80-*-*-m-*-iso8859-1")
1289 ("10 slant" "-adobe-courier-medium-o-normal--*-100-*-*-m-*-iso8859-1")
1290 ("12 slant" "-adobe-courier-medium-o-normal--*-120-*-*-m-*-iso8859-1")
1291 ("14 slant" "-adobe-courier-medium-o-normal--*-140-*-*-m-*-iso8859-1")
1292 ("18 slant" "-adobe-courier-medium-o-normal--*-180-*-*-m-*-iso8859-1")
1293 ("24 slant" "-adobe-courier-medium-o-normal--*-240-*-*-m-*-iso8859-1")
1294 ("8 bold slant" "-adobe-courier-bold-o-normal--*-80-*-*-m-*-iso8859-1")
1295 ("10 bold slant" "-adobe-courier-bold-o-normal--*-100-*-*-m-*-iso8859-1")
1296 ("12 bold slant" "-adobe-courier-bold-o-normal--*-120-*-*-m-*-iso8859-1")
1297 ("14 bold slant" "-adobe-courier-bold-o-normal--*-140-*-*-m-*-iso8859-1")
1298 ("18 bold slant" "-adobe-courier-bold-o-normal--*-180-*-*-m-*-iso8859-1")
1299 ("24 bold slant" "-adobe-courier-bold-o-normal--*-240-*-*-m-*-iso8859-1"))
07a78410
RS
1300 )
1301 "X fonts suitable for use in Emacs.")
1302
1900a92b 1303(defun mouse-set-font (&rest fonts)
07a78410
RS
1304 "Select an emacs font from a list of known good fonts"
1305 (interactive
1306 (x-popup-menu last-nonmenu-event x-fixed-font-alist))
df4de8c6
KH
1307 (if fonts
1308 (let (font)
1309 (while fonts
1310 (condition-case nil
1311 (progn
3fadec1a 1312 (set-default-font (car fonts))
df4de8c6
KH
1313 (setq font (car fonts))
1314 (setq fonts nil))
3fadec1a
RS
1315 (error
1316 (setq fonts (cdr fonts)))))
df4de8c6 1317 (if (null font)
3fadec1a 1318 (error "Font not found")))))
cc0a8174
JB
1319\f
1320;;; Bindings for mouse commands.
1321
fcfc3c63 1322(define-key global-map [down-mouse-1] 'mouse-drag-region)
dbc4e1c1 1323(global-set-key [mouse-1] 'mouse-set-point)
dbc4e1c1 1324(global-set-key [drag-mouse-1] 'mouse-set-region)
fcfc3c63 1325
e37de120
RS
1326;; These are tested for in mouse-drag-region.
1327(global-set-key [double-mouse-1] 'mouse-set-point)
1328(global-set-key [triple-mouse-1] 'mouse-set-point)
1329
dbc4e1c1
JB
1330(global-set-key [mouse-2] 'mouse-yank-at-click)
1331(global-set-key [mouse-3] 'mouse-save-then-kill)
8b34e79d 1332
dbc4e1c1
JB
1333;; By binding these to down-going events, we let the user use the up-going
1334;; event to make the selection, saving a click.
1335(global-set-key [C-down-mouse-1] 'mouse-buffer-menu)
1336(global-set-key [C-down-mouse-3] 'mouse-set-font)
07a78410 1337
8b34e79d
RS
1338;; Replaced with dragging mouse-1
1339;; (global-set-key [S-mouse-1] 'mouse-set-mark)
947da0c4 1340
3c2dd2c0
RS
1341(global-set-key [mode-line mouse-1] 'mouse-select-window)
1342(global-set-key [mode-line mouse-2] 'mouse-delete-other-windows)
dbc4e1c1 1343(global-set-key [mode-line mouse-3] 'mouse-delete-window)
3c2dd2c0 1344(global-set-key [mode-line C-mouse-2] 'mouse-split-window-horizontally)
9926ab64 1345(global-set-key [vertical-scroll-bar C-mouse-2] 'mouse-split-window-vertically)
b6522df6 1346(global-set-key [vertical-line C-mouse-2] 'mouse-split-window-vertically)
49116ac0
JB
1347
1348(provide 'mouse)
1349
6594deb0 1350;;; mouse.el ends here