1 ;;; hmouse-key.el --- Load "hmouse-sh.el" or "hmouse-reg.el" for Smart Key bindings.
3 ;; Copyright (C) 1994-1995, 2006 Free Software Foundation, Inc.
4 ;; Developed with support from Motorola Inc.
6 ;; Author: Bob Weiner, Brown U.
7 ;; Maintainer: Mats Lidell <matsl@contactor.se>
8 ;; Keywords: hypermedia, mouse
10 ;; This file is part of GNU Hyperbole.
12 ;; GNU Hyperbole is free software; you can redistribute it and/or
13 ;; modify it under the terms of the GNU General Public License as
14 ;; published by the Free Software Foundation; either version 3, or (at
15 ;; your option) any later version.
17 ;; GNU Hyperbole is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 ;; General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 ;; Boston, MA 02110-1301, USA.
29 ;; Supports Epoch, Lucid Emacs, X, Sunview, NEXTSTEP, and Apollo DM
32 ;; 'hmouse-shift-buttons' globally binds the Action and Assist Mouse Keys
33 ;; to either shifted or unshifted mouse buttons.
35 ;; 'hmouse-toggle-bindings' may be bound to a key. It switches between
36 ;; the Hyperbole mouse bindings and previous mouse key bindings any time
37 ;; after 'hmouse-shift-buttons' has been called.
43 ;;; Other required Elisp libraries
48 (require 'h-skip-bytec "h-skip-bytec.lsp")
54 (eval (cdr (assoc hyperb:window-system
56 ;; XEmacs and Emacs 19 pre-load their mouse libraries, so
57 ;; we shouldn't have to require them here.
59 ("xterm" . (require 'x-mouse)) ; X
60 ("epoch" . (require 'mouse)) ; UofI Epoch
61 ("next" . (load "eterm-fns" t)) ; NeXTstep
62 ("sun" . (require 'sun-fns)) ; SunView
63 ("apollo" . (require 'apollo)) ; Display Manager
70 (defun hmouse-set-bindings (key-binding-list)
71 "Sets mouse keys used as Smart Keys to bindings in KEY-BINDING-LIST.
72 KEY-BINDING-LIST is the value returned by 'hmouse-get-bindings' prior to
76 ;; GNU Emacs 19, Lucid Emacs, XEmacs or InfoDock
77 ((or (if (not noninteractive) (or hyperb:xemacs-p hyperb:emacs19-p))
78 (equal hyperb:window-system "xemacs"))
81 (lambda (key-and-binding)
82 (global-set-key (car key-and-binding) (cdr key-and-binding))))
86 ((equal hyperb:window-system "xterm")
89 (lambda (key-and-binding)
90 (define-key mouse-map (car key-and-binding) (cdr key-and-binding))))
94 ((equal hyperb:window-system "epoch")
97 (lambda (key-and-binding)
98 (aset mouse::global-map (car key-and-binding)
99 (cdr key-and-binding))))
103 ((or (equal hyperb:window-system "next")
104 (equal hyperb:window-system "sun"))
107 (lambda (key-and-binding)
108 (global-set-mouse (car key-and-binding) (cdr key-and-binding))))
111 ;; Apollo Display Manager
112 ((equal hyperb:window-system "apollo")
113 (if (string< emacs-version "18.58")
116 (lambda (key-and-binding)
117 (global-set-key (car key-and-binding) (cdr key-and-binding))))
121 (lambda (key-and-binding)
122 (define-key 'apollo-prefix (car key-and-binding)
123 (cdr key-and-binding))))
124 key-binding-list)))))
126 (defun hmouse-shift-buttons (&optional arg)
127 "Selects between shifted and unshifted Action and Assist mouse buttons.
128 With optional prefix ARG, use shifted buttons if ARG is positive or use
129 unshifted buttons otherwise. If ARG is nil, shifted buttons are used and
130 under InfoDock the middle button also acts as an Action Key."
132 (setq hmouse-shift-flag (if arg
133 (> (prefix-numeric-value arg) 0)
134 (not (and (boundp 'infodock-version)
136 (if hmouse-shift-flag
137 ;; Action Key = shift-middle mouse key. Assist Key = shift-right mouse
138 ;; key. Standard Hyperbole configuration.
140 ;; Action Key = middle mouse key; Assist Key = right mouse key
141 ;; InfoDock actually moves the Assist Key to the shift-right mouse key so
142 ;; that the right key can be used for popup menus.
144 ;; Replace any original mouse bindings before moving Hyperbole bindings and
145 ;; then force reinitialization of hmouse-previous-bindings.
146 (if (and hmouse-bindings-flag hmouse-previous-bindings)
147 (hmouse-set-bindings hmouse-previous-bindings))
148 (setq hmouse-bindings-flag nil
149 hmouse-previous-bindings nil)
150 ;; Initialize Hyperbole mouse bindings.
153 (message "%s Action and Assist mouse buttons in use."
154 (if hmouse-shift-flag "Shifted" "Unshifted"))))
156 (defun hmouse-toggle-bindings ()
157 "Toggles between Smart Key mouse settings and their prior bindings."
159 (let ((key-binding-list (if hmouse-bindings-flag
160 hmouse-previous-bindings
162 (other-list-var (if hmouse-bindings-flag
164 'hmouse-previous-bindings)))
167 (set other-list-var (hmouse-get-bindings))
168 (hmouse-set-bindings key-binding-list)
169 (message "%s mouse bindings in use."
170 (if (setq hmouse-bindings-flag (not hmouse-bindings-flag))
171 "Smart Key" "Personal")))
172 (error "(hmouse-toggle-bindings): Null %s." other-list-var))))
174 (defun hmouse-set-point-at (set-point-arg-list)
175 "Sets point to cursor position using SET-POINT-ARG-LIST and returns t.
176 If 'hmouse-set-point-command' is not bound to a function, this does nothing
178 (if (fboundp hmouse-set-point-command)
180 (if (and (boundp 'drag-zone) drag-zone)
181 (progn (delete-zone drag-zone)
182 (setq drag-zone nil))
183 (and (boundp 'drag-button) drag-button
184 (progn (delete-button drag-button)
185 (setq drag-button nil))))
186 (or (if set-point-arg-list
187 (funcall hmouse-set-point-command set-point-arg-list)
188 (funcall hmouse-set-point-command))
192 ;;; Private functions
195 (if (fboundp 'bind-apollo-mouse-button)
197 (if (string< emacs-version "18.58")
198 (defun apollo-mouse-key-and-binding (mouse-button)
199 "Returns binding for an Apollo MOUSE-BUTTON (a string) or nil if none."
200 (interactive "sMouse Button: ")
201 (let ((numeric-code (cdr (assoc mouse-button *apollo-mouse-buttons*))))
202 (if (null numeric-code)
203 (error "(hmouse-key): %s is not a valid Apollo mouse key name."
205 (if (stringp numeric-code)
207 (cdr (assoc numeric-code *apollo-mouse-buttons*))))
208 (let ((key-sequence (concat "\M-*" (char-to-string numeric-code))))
209 (cons key-sequence (global-key-binding key-sequence)))))
210 (defun apollo-mouse-key-and-binding (mouse-button)
211 "Returns binding for an Apollo MOUSE-BUTTON (a string) or nil if none."
212 (interactive "sMouse Button: ")
213 (let ((numeric-code (cdr (assoc mouse-button *apollo-mouse-buttons*))))
214 (if (null numeric-code)
215 (error "(hmouse-key): %s is not a valid Apollo mouse key name."
217 (if (stringp numeric-code)
219 (cdr (assoc numeric-code *apollo-mouse-buttons*))))
220 (let ((key-sequence (char-to-string numeric-code)))
221 (cons key-sequence (lookup-key 'apollo-prefix key-sequence)))))
223 (defun apollo-mouse-move-point (&optional no-mark)
224 "Used so that pressing the left mouse button, moving the cursor, and
225 releasing the left mouse button leaves the mark set to the initial position
226 and the point set to the final position. Useful for easily marking regions
227 of text. If the left mouse button is pressed and released at the same place,
228 the mark is left at the original position of the character cursor.
230 Returns (x y) frame coordinates of point in columns and lines."
232 (let* ((opoint (point))
233 (owindow (selected-window))
234 (x (- (read-char) 8))
235 (y (- (read-char) 8))
236 (edges (window-edges))
238 (while (and (not (eq window (selected-window)))
239 (or (< y (nth 1 edges))
242 (>= x (nth 2 edges))))
243 (setq window (next-window window))
244 (setq edges (window-edges window)))
245 (if (and window (not (eq window (selected-window))))
247 (if (and (not *apollo-mouse-move-point-allow-minibuffer-exit*)
248 (eq (selected-window) (minibuffer-window)))
249 (error "Cannot use mouse to leave minibuffer!"))
250 (if (eq window (minibuffer-window))
251 (error "Cannot use mouse to enter minibuffer!"))))
252 (if window (select-window window))
253 (move-to-window-line (- y (nth 1 edges)))
254 (let* ((width-1 (1- (window-width window)))
255 (wraps (/ (current-column) width-1))
256 (prompt-length (if (eq (selected-window) (minibuffer-window))
257 (minibuffer-prompt-length)
259 (move-to-column (+ (- x (nth 0 edges) prompt-length)
262 (progn (setq window (selected-window))
263 (if (eq owindow window)
264 (if (equal opoint (point))
266 (select-window owindow)
268 (select-window window)))
269 (set-mark-command nil))
270 ;; Return (x y) coords of point in column and frame line numbers.
274 (defun action-key-depress (&rest args)
277 (setq action-key-depress-prev-point (point-marker)
278 action-key-depressed-flag t
279 action-key-depress-args (hmouse-set-point args)
280 action-key-depress-window (selected-window)
281 action-key-release-args nil
282 action-key-release-window nil
283 action-key-release-prev-point nil)
284 (if assist-key-depressed-flag
285 (or action-key-help-flag
286 (setq assist-key-help-flag t))))
288 (defun assist-key-depress (&rest args)
291 (setq assist-key-depress-prev-point (point-marker)
292 assist-key-depressed-flag t
293 assist-key-depress-args (hmouse-set-point args)
294 assist-key-depress-window (selected-window)
295 assist-key-release-args nil
296 assist-key-release-window nil
297 assist-key-release-prev-point nil)
298 (if action-key-depressed-flag
299 (or assist-key-help-flag
300 (setq action-key-help-flag t)))
303 (defun action-key-depress-emacs19 (event)
306 (action-key-depress event))
308 (defun assist-key-depress-emacs19 (event)
311 (assist-key-depress event))
313 (defun action-mouse-key-emacs19 (event)
314 "Set point to the current mouse cursor position and execute 'action-key'.
315 EVENT will be passed to 'hmouse-function'."
317 (action-mouse-key (hmouse-key-release-args-emacs19 event)))
319 (defun assist-mouse-key-emacs19 (event)
320 "Set point to the current mouse cursor position and execute 'action-key'.
321 EVENT will be passed to 'hmouse-function'."
323 (assist-mouse-key (hmouse-key-release-args-emacs19 event)))
325 (defun hmouse-key-release-args-emacs19 (event)
326 (let ((ev-type-str (and (listp event) (symbol-name (car event)))))
327 (if (or (and ev-type-str
328 (string-match "\\(double\\|triple\\)-mouse" ev-type-str))
329 (not (= (length event) 3)))
331 ;; Remove depress coordinates and send only release coordinates.
332 (list (car event) (nth 2 event)))))
334 (defun hmouse-move-point-xemacs ()
336 (mouse-set-point current-mouse-event)
337 ;; Catch "not in a window" errors, e.g. on modeline
340 (defun hmouse-move-point-eterm (arg-list)
341 (apply 'mouse-move-point arg-list))
344 ;;; Private variables
347 (defvar hmouse-bindings nil
348 "List of (key . binding) pairs for Smart Mouse Keys.")
350 (defvar hmouse-bindings-flag nil
351 "True if Smart Key mouse bindings are in use, else nil.")
353 (defvar hmouse-previous-bindings nil
354 "List of previous (key . binding) pairs for mouse keys used as Smart Keys.")
356 (provide 'hmouse-key)
358 ;;; hmouse-key.el ends here