Commit | Line | Data |
---|---|---|
cc1f74de JB |
1 | ;;; bg-mouse.el --- GNU Emacs code for BBN Bitgraph mouse |
2 | ||
5b0d63bc | 3 | ;; Copyright (C) 2001, 2002, 2003, 2004, 2005, |
2f043267 | 4 | ;; 2006, 2007, 2008 Free Software Foundation, Inc. |
cc1f74de JB |
5 | |
6 | ;; Author: John Robinson <jr@bbn-unix.arpa> | |
7 | ;; Stephen Gildea <gildea@bbn.com> | |
8 | ;; Maintainer: FSF | |
9 | ;; Keywords: hardware | |
10 | ||
11 | ;; This file is part of GNU Emacs. | |
12 | ||
13 | ;; GNU Emacs is free software; you can redistribute it and/or modify | |
14 | ;; it under the terms of the GNU General Public License as published by | |
5a9dffec | 15 | ;; the Free Software Foundation; either version 3, or (at your option) |
cc1f74de JB |
16 | ;; any later version. |
17 | ||
18 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
19 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 | ;; GNU General Public License for more details. | |
22 | ||
23 | ;; You should have received a copy of the GNU General Public License | |
24 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | |
25 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
26 | ;; Boston, MA 02110-1301, USA. | |
27 | ||
28 | ;;; Commentary: | |
29 | ||
30 | ;;; Code: | |
31 | ||
32 | ;;; Original version by John Robinson (jr@bbn-unix.arpa, bbncca!jr), Oct 1985 | |
33 | ;;; Modularized and enhanced by gildea@bbn.com Nov 1987 | |
34 | ;;; Time stamp <89/03/21 14:27:08 gildea> | |
35 | ||
36 | ;;; User customization option: | |
37 | ||
38 | (defvar bg-mouse-fast-select-window nil | |
39 | "*Non-nil for mouse hits to select new window, then execute; else just select.") | |
40 | ||
41 | ;;; These numbers are summed to make the index into the mouse-map. | |
42 | ;;; The low three bits correspond to what the mouse actually sends. | |
43 | (defconst bg-button-r 1) | |
44 | (defconst bg-button-m 2) | |
45 | (defconst bg-button-c 2) | |
46 | (defconst bg-button-l 4) | |
47 | (defconst bg-in-modeline 8) | |
48 | (defconst bg-in-scrollbar 16) | |
49 | (defconst bg-in-minibuf 24) | |
50 | ||
51 | ;;; semicolon screws up indenting, so use this instead | |
52 | (defconst semicolon ?\;) | |
53 | ||
623f1465 JB |
54 | (defvar bg-mouse-x) |
55 | (defvar bg-mouse-y) | |
56 | (defvar bg-cursor-window) | |
57 | ;; This variable does not exist since 1991, so it's a safe bet | |
58 | ;; this package is not really used anymore. Still... | |
59 | (defvar mouse-map) | |
cc1f74de JB |
60 | |
61 | ;;; Defuns: | |
62 | ||
63 | (defun bg-mouse-report (prefix-arg) | |
64 | "Read, parse, and execute a BBN BitGraph mouse click. | |
65 | ||
66 | L-- move point | These apply for mouse click in a window. | |
67 | --R set mark | If bg-mouse-fast-select-window is nil, | |
68 | L-R kill region | these commands on a nonselected window | |
69 | -C- move point and yank | just select that window. | |
70 | LC- yank-pop | | |
71 | -CR or LCR undo | \"Scroll bar\" is right-hand window column. | |
72 | ||
73 | on modeline: on \"scroll bar\": in minibuffer: | |
74 | L-- scroll-up line to top execute-extended-command | |
75 | --R scroll-down line to bottom eval-expression | |
76 | -C- proportional goto-char line to middle suspend-emacs | |
77 | ||
78 | To reinitialize the mouse if the terminal is reset, type ESC : RET" | |
79 | (interactive "P") | |
80 | (bg-get-tty-num semicolon) | |
81 | (let* | |
82 | ((screen-mouse-x (min (1- (frame-width)) ;don't hit column 86! | |
83 | (/ (bg-get-tty-num semicolon) 9))) | |
84 | (screen-mouse-y (- (1- (frame-height)) ;assume default font size. | |
85 | (/ (bg-get-tty-num semicolon) 16))) | |
86 | (bg-mouse-buttons (% (bg-get-tty-num ?c) 8)) | |
87 | (bg-mouse-window (bg-window-from-x-y screen-mouse-x screen-mouse-y)) | |
88 | (bg-cursor-window (selected-window)) | |
89 | (edges (window-edges bg-mouse-window)) | |
90 | (minibuf-p (= screen-mouse-y (1- (frame-height)))) | |
91 | (in-modeline-p (and (not minibuf-p) | |
92 | (= screen-mouse-y (1- (nth 3 edges))))) | |
93 | (in-scrollbar-p (and (not minibuf-p) (not in-modeline-p) | |
94 | (>= screen-mouse-x (1- (nth 2 edges))))) | |
95 | (same-window-p (eq bg-mouse-window bg-cursor-window)) | |
96 | (in-minibuf-p (and minibuf-p | |
97 | (not bg-mouse-window))) ;minibuf must be inactive | |
98 | (bg-mode-bits (+ (if in-minibuf-p bg-in-minibuf 0) | |
99 | (if in-modeline-p bg-in-modeline 0) | |
100 | (if in-scrollbar-p bg-in-scrollbar 0))) | |
101 | (bg-command | |
102 | (lookup-key mouse-map | |
103 | (char-to-string (+ bg-mode-bits bg-mouse-buttons)))) | |
104 | (bg-mouse-x (- screen-mouse-x (nth 0 edges))) | |
105 | (bg-mouse-y (- screen-mouse-y (nth 1 edges)))) | |
106 | (cond ((or in-modeline-p in-scrollbar-p) | |
107 | (select-window bg-mouse-window) | |
108 | (bg-command-execute bg-command) | |
109 | (select-window bg-cursor-window)) | |
110 | ((or same-window-p in-minibuf-p) | |
111 | (bg-command-execute bg-command)) | |
112 | (t ;in another window | |
113 | (select-window bg-mouse-window) | |
114 | (if bg-mouse-fast-select-window | |
115 | (bg-command-execute bg-command))) | |
116 | ))) | |
117 | ||
118 | \f | |
119 | ;;; Library of commands: | |
120 | ||
121 | (defun bg-set-point () | |
122 | "Move point to location of BitGraph mouse." | |
123 | (interactive) | |
124 | (bg-move-point-to-x-y bg-mouse-x bg-mouse-y) | |
125 | (setq this-command 'next-line) ;make subsequent line moves work | |
126 | (setq temporary-goal-column bg-mouse-x)) | |
127 | ||
128 | (defun bg-set-mark () | |
129 | "Set mark at location of BitGraph mouse." | |
130 | (interactive) | |
131 | (push-mark) | |
132 | (bg-move-point-to-x-y bg-mouse-x bg-mouse-y) | |
133 | (exchange-point-and-mark)) | |
134 | ||
135 | (defun bg-yank () | |
136 | "Move point to location of BitGraph mouse and yank." | |
137 | (interactive "*") | |
138 | (bg-move-point-to-x-y bg-mouse-x bg-mouse-y) | |
139 | (setq this-command 'yank) | |
140 | (yank)) | |
141 | ||
142 | (defun yank-pop-1 () | |
143 | (interactive "*") | |
144 | (yank-pop 1)) | |
145 | ||
146 | (defun bg-yank-or-pop () | |
147 | "Move point to location of BitGraph mouse and yank. If last command | |
148 | was a yank, do a yank-pop." | |
149 | (interactive "*") | |
150 | (if (eq last-command 'yank) | |
151 | (yank-pop 1) | |
152 | (bg-yank))) | |
153 | ||
154 | ;;; In 18.51, Emacs Lisp doesn't provide most-positive-fixnum | |
155 | (defconst bg-most-positive-fixnum 8388607) | |
156 | ||
157 | (defun bg-move-by-percentage () | |
158 | "Go to location in buffer that is the same percentage of the way | |
159 | through the buffer as the BitGraph mouse's X position in the window." | |
160 | (interactive) | |
161 | ;; check carefully for overflow in intermediate calculations | |
162 | (goto-char | |
163 | (cond ((zerop bg-mouse-x) | |
164 | 0) | |
165 | ((< (buffer-size) (/ bg-most-positive-fixnum bg-mouse-x)) | |
166 | ;; no danger of overflow: compute it exactly | |
167 | (/ (* bg-mouse-x (buffer-size)) | |
168 | (1- (window-width)))) | |
169 | (t | |
170 | ;; overflow possible: approximate | |
171 | (* (/ (buffer-size) (1- (window-width))) | |
172 | bg-mouse-x)))) | |
173 | (beginning-of-line) | |
174 | (what-cursor-position)) | |
175 | ||
176 | (defun bg-mouse-line-to-top () | |
177 | "Scroll the line pointed to by the BitGraph mouse to the top of the window." | |
178 | (interactive) | |
179 | (scroll-up bg-mouse-y)) | |
180 | ||
181 | (defun bg-mouse-line-to-center () | |
182 | "Scroll the line pointed to by the BitGraph mouse to the center | |
183 | of the window" | |
184 | (interactive) | |
185 | (scroll-up (/ (+ 2 bg-mouse-y bg-mouse-y (- (window-height))) 2))) | |
186 | ||
187 | (defun bg-mouse-line-to-bottom () | |
188 | "Scroll the line pointed to by the mouse to the bottom of the window." | |
189 | (interactive) | |
190 | (scroll-up (+ bg-mouse-y (- 2 (window-height))))) | |
191 | ||
192 | (defun bg-kill-region () | |
193 | (interactive "*") | |
194 | (kill-region (region-beginning) (region-end))) | |
195 | ||
196 | (defun bg-insert-moused-sexp () | |
197 | "Insert a copy of the word (actually sexp) that the mouse is pointing at. | |
198 | Sexp is inserted into the buffer at point (where the text cursor is)." | |
199 | (interactive) | |
200 | (let ((moused-text | |
201 | (save-excursion | |
202 | (bg-move-point-to-x-y bg-mouse-x bg-mouse-y) | |
203 | (if (looking-at "\\s)") | |
204 | (forward-char 1) | |
205 | (forward-sexp 1)) | |
206 | (buffer-substring (save-excursion (backward-sexp 1) (point)) | |
207 | (point))))) | |
208 | (select-window bg-cursor-window) | |
209 | (delete-horizontal-space) | |
210 | (cond | |
211 | ((bolp) | |
212 | (indent-according-to-mode)) | |
213 | ;; In Lisp assume double-quote is closing; in Text assume opening. | |
214 | ;; Why? Because it does the right thing most often. | |
215 | ((save-excursion (forward-char -1) | |
216 | (and (not (looking-at "\\s\"")) | |
217 | (looking-at "[`'\"\\]\\|\\s("))) | |
218 | nil) | |
219 | (t | |
220 | (insert " "))) | |
221 | (insert moused-text) | |
222 | (or (eolp) | |
223 | (looking-at "\\s.\\|\\s)") | |
224 | (and (looking-at "'") (looking-at "\\sw")) ;hack for text mode | |
225 | (save-excursion (insert " "))))) | |
226 | \f | |
227 | ;;; Utility functions: | |
228 | ||
229 | (defun bg-get-tty-num (term-char) | |
230 | "Read from terminal until TERM-CHAR is read, and return intervening number. | |
231 | If non-numeric not matching TERM-CHAR, reprogram the mouse and signal an error." | |
232 | (let | |
233 | ((num 0) | |
234 | (char (- (read-char) 48))) | |
235 | (while (and (>= char 0) | |
236 | (<= char 9)) | |
237 | (setq num (+ (* num 10) char)) | |
238 | (setq char (- (read-char) 48))) | |
239 | (or (eq term-char (+ char 48)) | |
240 | (progn | |
241 | (bg-program-mouse) | |
242 | (error | |
243 | "Invalid data format in bg-mouse command: mouse reinitialized."))) | |
244 | num)) | |
245 | ||
246 | ;;; Note that this fails in the minibuf because move-to-column doesn't | |
247 | ;;; allow for the width of the prompt. | |
248 | (defun bg-move-point-to-x-y (x y) | |
249 | "Position cursor in window coordinates. | |
250 | X and Y are 0-based character positions in the window." | |
251 | (move-to-window-line y) | |
252 | ;; if not on a wrapped line, zero-column will be 0 | |
253 | (let ((zero-column (current-column)) | |
254 | (scroll-offset (window-hscroll))) | |
255 | ;; scrolling takes up column 0 to display the $ | |
256 | (if (> scroll-offset 0) | |
257 | (setq scroll-offset (1- scroll-offset))) | |
258 | (move-to-column (+ zero-column scroll-offset x)) | |
259 | )) | |
260 | ||
261 | ;;; Returns the window that screen position (x, y) is in or nil if none, | |
262 | ;;; meaning we are in the echo area with a non-active minibuffer. | |
263 | (defun bg-window-from-x-y (x y) | |
264 | "Find window corresponding to screen coordinates. | |
265 | X and Y are 0-based character positions on the screen." | |
266 | (get-window-with-predicate (lambda (w) | |
267 | (coordinates-in-window-p (cons x y) w)))) | |
268 | ||
269 | (defun bg-command-execute (bg-command) | |
270 | (if (commandp bg-command) | |
271 | (command-execute bg-command) | |
272 | (ding))) | |
273 | ||
274 | (defun bg-program-mouse () | |
275 | (send-string-to-terminal "\e:0;7;;;360;512;9;16;9;16c")) | |
276 | ||
277 | ;;; Note that the doc string for mouse-map (as defined in subr.el) | |
278 | ;;; says it is for the X-window mouse. This is wrong; that keymap | |
279 | ;;; should be used for your mouse no matter what terminal you have. | |
280 | ||
281 | (or (keymapp mouse-map) | |
282 | (setq mouse-map (make-keymap))) | |
283 | ||
284 | (defun bind-bg-mouse-click (click-code function) | |
285 | "Bind bg-mouse CLICK-CODE to run FUNCTION." | |
286 | (define-key mouse-map (char-to-string click-code) function)) | |
287 | ||
288 | (bind-bg-mouse-click bg-button-l 'bg-set-point) | |
289 | (bind-bg-mouse-click bg-button-m 'bg-yank) | |
290 | (bind-bg-mouse-click bg-button-r 'bg-set-mark) | |
291 | (bind-bg-mouse-click (+ bg-button-l bg-button-m) 'yank-pop-1) | |
292 | (bind-bg-mouse-click (+ bg-button-l bg-button-r) 'bg-kill-region) | |
293 | (bind-bg-mouse-click (+ bg-button-m bg-button-r) 'undo) | |
294 | (bind-bg-mouse-click (+ bg-button-l bg-button-m bg-button-r) 'undo) | |
295 | (bind-bg-mouse-click (+ bg-in-modeline bg-button-l) 'scroll-up) | |
296 | (bind-bg-mouse-click (+ bg-in-modeline bg-button-m) 'bg-move-by-percentage) | |
297 | (bind-bg-mouse-click (+ bg-in-modeline bg-button-r) 'scroll-down) | |
298 | (bind-bg-mouse-click (+ bg-in-scrollbar bg-button-l) 'bg-mouse-line-to-top) | |
299 | (bind-bg-mouse-click (+ bg-in-scrollbar bg-button-m) 'bg-mouse-line-to-center) | |
300 | (bind-bg-mouse-click (+ bg-in-scrollbar bg-button-r) 'bg-mouse-line-to-bottom) | |
301 | (bind-bg-mouse-click (+ bg-in-minibuf bg-button-l) 'execute-extended-command) | |
302 | (bind-bg-mouse-click (+ bg-in-minibuf bg-button-m) 'suspend-emacs) | |
303 | (bind-bg-mouse-click (+ bg-in-minibuf bg-button-r) 'eval-expression) | |
304 | ||
305 | (provide 'bg-mouse) | |
306 | ||
cbee283d | 307 | ;; arch-tag: b3d06605-2971-44b1-be2c-e49c24e1a8d3 |
cc1f74de | 308 | ;;; bg-mouse.el ends here |