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