Mercurial > emacs
comparison lisp/t-mouse.el @ 69189:ec62f416bd30
(t-mouse-tty): Use with-temp-buffer. Add more
terminal types.
(t-mouse-lispy-buffer-posn-from-coords): Remove. Use C
primitive...
(t-mouse-make-event-element): ...posn-at-x-y instead.
(t-mouse-make-event): Deal with Fedora Core 3.
(t-mouse-make-event): Don't sink the `stupid text mode menubar'.
(t-mouse-mouse-position-function): New function. Use it instead
of advising mouse-position.
(t-mouse-mode): New minor mode.
(t-mouse-stop, t-mouse-run): Remove. Use t-mouse-mode instead.
author | Nick Roberts <nickrob@snap.net.nz> |
---|---|
date | Mon, 27 Feb 2006 22:46:06 +0000 |
parents | ee54b3a792ff |
children | 4c0f4c81c362 |
comparison
equal
deleted
inserted
replaced
69188:bbe4019f0045 | 69189:ec62f416bd30 |
---|---|
1 ;;; t-mouse.el --- mouse support within the text terminal | 1 ;;; t-mouse.el --- mouse support within the text terminal |
2 | 2 |
3 ;;; Copyright (C) 1994,1995 Alessandro Rubini <rubini@linux.it> | 3 ;; Authors: Alessandro Rubini and Ian T Zimmerman |
4 ;;; parts are by Ian T Zimmermann <itz@rahul.net>, 1995,1998 | 4 ;; Maintainer: Nick Roberts <nickrob@gnu.org> |
5 | |
6 ;; Maintainer: gpm mailing list: gpm@prosa.it | |
7 ;; Keywords: mouse gpm linux | 5 ;; Keywords: mouse gpm linux |
8 | 6 |
9 ;;; This program is distributed in the hope that it will be useful, | 7 ;; Copyright (C) 1994,1995 Alessandro Rubini <rubini@linux.it> |
10 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | 8 ;; parts are by Ian T Zimmermann <itz@rahul.net>, 1995,1998 |
11 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 9 ;; Copyright (C) 2006 |
12 ;;; GNU General Public License for more details. | 10 ;; Free Software Foundation, Inc. |
13 | 11 |
14 ;;; You should have received a copy of the GNU General Public License | 12 ;; This file is part of GNU Emacs. |
15 ;;; along with GNU Emacs; see the file COPYING. If not, write to | 13 |
16 ;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | 14 ;; GNU Emacs is free software; you can redistribute it and/or modify |
15 ;; it under the terms of the GNU General Public License as published by | |
16 ;; the Free Software Foundation; either version 2, or (at your option) | |
17 ;; any later version. | |
18 | |
19 ;; GNU Emacs is distributed in the hope that it will be useful, | |
20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
22 ;; GNU General Public License for more details. | |
23 | |
24 ;; You should have received a copy of the GNU General Public License | |
25 ;; along with GNU Emacs; see the file COPYING. If not, write to the | |
26 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
27 ;; Boston, MA 02110-1301, USA. | |
17 | 28 |
18 ;;; Commentary: | 29 ;;; Commentary: |
19 | 30 |
20 ;; This package provides access to mouse event as reported by the | 31 ;; This package provides access to mouse event as reported by the |
21 ;; gpm-Linux package. It uses the program "mev" to get mouse events. | 32 ;; gpm-Linux package. It uses the program "mev" to get mouse events. |
22 ;; It tries to reproduce the functionality offered by emacs under X. | 33 ;; It tries to reproduce the functionality offered by emacs under X. |
23 ;; The "gpm" server runs under Linux, so this package is rather | 34 ;; The "gpm" server runs under Linux, so this package is rather |
24 ;; Linux-dependent. | 35 ;; Linux-dependent. |
25 | 36 |
26 ;; Developed for GNU Emacs 19.34, likely won't work with many others | 37 ;; Modified by Nick Roberts for Emacs 22. In particular, the mode-line is |
27 ;; too much internals dependent cruft here. | 38 ;; now position sensitive. |
28 | |
29 | |
30 (require 'advice) | |
31 | 39 |
32 (defvar t-mouse-process nil | 40 (defvar t-mouse-process nil |
33 "Embeds the process which passes mouse events to emacs. | 41 "Embeds the process which passes mouse events to emacs. |
34 It is used by the program t-mouse.") | 42 It is used by the program t-mouse.") |
35 | 43 |
67 ;; get the number of the current virtual console | 75 ;; get the number of the current virtual console |
68 | 76 |
69 (defun t-mouse-tty () | 77 (defun t-mouse-tty () |
70 "Returns number of virtual terminal Emacs is running on, as a string. | 78 "Returns number of virtual terminal Emacs is running on, as a string. |
71 For example, \"2\" for /dev/tty2." | 79 For example, \"2\" for /dev/tty2." |
72 (let ((buffer (generate-new-buffer "*t-mouse*"))) | 80 (with-temp-buffer |
73 (call-process "ps" nil buffer nil "h" (format "%s" (emacs-pid))) | 81 (call-process "ps" nil t nil "h" (format "%s" (emacs-pid))) |
74 (prog1 (save-excursion | 82 (goto-char (point-min)) |
75 (set-buffer buffer) | 83 (if (or |
76 (goto-char (point-min)) | 84 ;; Many versions of "ps", all different.... |
77 (if (or | 85 (re-search-forward " +tty\\(.?[0-9a-f]\\)" nil t) |
78 ;; Many versions of "ps", all different.... | 86 (re-search-forward "p \\([0-9a-f]\\)" nil t) |
79 (re-search-forward " +tty\\(.?[0-9a-f]\\)" nil t) | 87 (re-search-forward "v0\\([0-9a-f]\\)" nil t) |
80 (re-search-forward "p \\([0-9a-f]\\)" nil t) | 88 (re-search-forward "[0-9]+ +\\([0-9]+\\)" nil t) |
81 (re-search-forward "v0\\([0-9a-f]\\)" nil t) | 89 (re-search-forward "[\\t ]*[0-9]+[\\t ]+\\([0-9]+\\)" nil t) |
82 (re-search-forward "[0-9]+ +\\([0-9]+\\)" nil t) | 90 (re-search-forward " +vc/\\(.?[0-9a-f]\\)" nil t) |
83 (re-search-forward "[\\t ]*[0-9]+[\\t ]+\\([0-9]+\\)" nil t)) | 91 (re-search-forward " +pts/\\(.?[0-9a-f]\\)" nil t)) |
84 (buffer-substring (match-beginning 1) (match-end 1)))) | 92 (buffer-substring (match-beginning 1) (match-end 1))))) |
85 (kill-buffer buffer)))) | |
86 | 93 |
87 | 94 |
88 ;; due to a horrible kludge in Emacs' keymap handler | 95 ;; due to a horrible kludge in Emacs' keymap handler |
89 ;; (read_key_sequence) mouse clicks on funny parts of windows generate | 96 ;; (read_key_sequence) mouse clicks on funny parts of windows generate |
90 ;; TWO events, the first being a dummy of the sort '(mode-line). | 97 ;; TWO events, the first being a dummy of the sort '(mode-line). |
126 (let ((event-sym (event-convert-list (nth 0 all-sets)))) | 133 (let ((event-sym (event-convert-list (nth 0 all-sets)))) |
127 (if (not (get event-sym 'event-kind)) | 134 (if (not (get event-sym 'event-kind)) |
128 (put event-sym 'event-kind 'mouse-click))) | 135 (put event-sym 'event-kind 'mouse-click))) |
129 (setq all-sets (cdr all-sets)))) | 136 (setq all-sets (cdr all-sets)))) |
130 | 137 |
131 | |
132 ;;; This fun is partly Copyright (C) 1994 Per Abrahamsen <abraham@iesd.auc.dk> | |
133 ;; This is basically a feeble attempt to mimic what the c function | |
134 ;; buffer_posn_from_coords in dispnew.c does. I wish that function | |
135 ;; were exported to Lisp. | |
136 | |
137 (defun t-mouse-lispy-buffer-posn-from-coords (w col line) | |
138 "Return buffer position of character at COL and LINE within window W. | |
139 COL and LINE are glyph coordinates, relative to W topleft corner." | |
140 (save-window-excursion | |
141 (select-window w) | |
142 (save-excursion | |
143 (move-to-window-line line) | |
144 (move-to-column (+ col (current-column) | |
145 (if (not (window-minibuffer-p w)) 0 | |
146 (- (minibuffer-prompt-width))) | |
147 (max 0 (1- (window-hscroll))))) | |
148 (point)))) | |
149 | |
150 ;; compute one element of the form (WINDOW BUFFERPOS (COL . ROW) TIMESTAMP) | |
151 | |
152 (defun t-mouse-make-event-element (x-dot-y-avec-time) | 138 (defun t-mouse-make-event-element (x-dot-y-avec-time) |
153 (let* ((x-dot-y (nth 0 x-dot-y-avec-time)) | 139 (let* ((x-dot-y (nth 0 x-dot-y-avec-time)) |
154 (x (car x-dot-y)) | 140 (x (car x-dot-y)) |
155 (y (cdr x-dot-y)) | 141 (y (cdr x-dot-y)) |
156 (timestamp (nth 1 x-dot-y-avec-time)) | |
157 (w (window-at x y)) | 142 (w (window-at x y)) |
158 (left-top-right-bottom (window-edges w)) | 143 (ltrb (window-edges w)) |
159 (left (nth 0 left-top-right-bottom)) | 144 (left (nth 0 ltrb)) |
160 (top (nth 1 left-top-right-bottom)) | 145 (top (nth 1 ltrb))) |
161 (right (nth 2 left-top-right-bottom)) | 146 (if w (posn-at-x-y (- x left) (- y top) w t) |
162 (bottom (nth 3 left-top-right-bottom)) | 147 (append (list nil 'menu-bar) (nthcdr 2 (posn-at-x-y x y w t)))))) |
163 (coords-or-part (coordinates-in-window-p x-dot-y w))) | |
164 (cond | |
165 ((consp coords-or-part) | |
166 (let ((wx (car coords-or-part)) (wy (cdr coords-or-part))) | |
167 (if (< wx (- right left 1)) | |
168 (list w | |
169 (t-mouse-lispy-buffer-posn-from-coords w wx wy) | |
170 coords-or-part timestamp) | |
171 (list w 'vertical-scroll-bar | |
172 (cons (1+ wy) (- bottom top)) timestamp)))) | |
173 ((eq coords-or-part 'mode-line) | |
174 (list w 'mode-line (cons (- x left) 0) timestamp)) | |
175 ((eq coords-or-part 'vertical-line) | |
176 (list w 'vertical-line (cons 0 (- y top)) timestamp))))) | |
177 | 148 |
178 ;;; This fun is partly Copyright (C) 1994 Per Abrahamsen <abraham@iesd.auc.dk> | 149 ;;; This fun is partly Copyright (C) 1994 Per Abrahamsen <abraham@iesd.auc.dk> |
179 | |
180 (defun t-mouse-make-event () | 150 (defun t-mouse-make-event () |
181 "Makes a Lisp style event from the contents of mouse input accumulator. | 151 "Makes a Lisp style event from the contents of mouse input accumulator. |
182 Also trims the accumulator by all the data used to build the event." | 152 Also trims the accumulator by all the data used to build the event." |
183 (let (ob (ob-pos (condition-case nil | 153 (let (ob (ob-pos (condition-case nil |
184 (read-from-string t-mouse-filter-accumulator) | 154 (progn |
155 ;; this test is just needed for Fedora Core 3 | |
156 (if (string-match "STILL RUNNING_1\n" | |
157 t-mouse-filter-accumulator) | |
158 (setq t-mouse-filter-accumulator | |
159 (substring | |
160 t-mouse-filter-accumulator (match-end 0)))) | |
161 (read-from-string t-mouse-filter-accumulator)) | |
185 (error nil)))) | 162 (error nil)))) |
186 (if (not ob-pos) nil | 163 ;; this test is just needed for Fedora Core 3 |
164 (if (or (eq (car ob-pos) 'STILL) (eq (car ob-pos) '***) (not ob-pos)) | |
165 nil | |
187 (setq ob (car ob-pos)) | 166 (setq ob (car ob-pos)) |
188 (setq t-mouse-filter-accumulator | 167 (setq t-mouse-filter-accumulator |
189 (substring t-mouse-filter-accumulator (cdr ob-pos))) | 168 (substring t-mouse-filter-accumulator (cdr ob-pos))) |
190 | 169 |
191 ;;now the real work | 170 ;;now the real work |
192 | 171 |
193 (let ((event-type (nth 0 ob)) | 172 (let ((event-type (nth 0 ob)) |
194 (current-xy-avec-time (nth 1 ob)) | 173 (current-xy-avec-time (nth 1 ob)) |
195 (type-switch (length ob))) | 174 (type-switch (length ob))) |
196 | |
197 (if t-mouse-fix-21 | 175 (if t-mouse-fix-21 |
198 (let | 176 (let |
199 ;;Acquire the event's symbol's name. | 177 ;;Acquire the event's symbol's name. |
200 ((event-name-string (symbol-name event-type)) | 178 ((event-name-string (symbol-name event-type)) |
201 end-of-root-event-name | 179 end-of-root-event-name |
221 (setq t-mouse-current-xy (nth 0 current-xy-avec-time)) | 199 (setq t-mouse-current-xy (nth 0 current-xy-avec-time)) |
222 | 200 |
223 ;;events have many types but fortunately they differ in length | 201 ;;events have many types but fortunately they differ in length |
224 | 202 |
225 (cond | 203 (cond |
226 ;;sink all events on the stupid text mode menubar. | |
227 ((and menu-bar-mode (eq 0 (cdr t-mouse-current-xy))) nil) | |
228 ((= type-switch 4) ;must be drag | 204 ((= type-switch 4) ;must be drag |
229 (let ((count (nth 2 ob)) | 205 (let ((count (nth 2 ob)) |
230 (start-element | 206 (start-element |
231 (or t-mouse-drag-start | 207 (or t-mouse-drag-start |
232 (t-mouse-make-event-element (nth 3 ob)))) | 208 (t-mouse-make-event-element (nth 3 ob)))) |
248 (list (if (eq 'vertical-scroll-bar | 224 (list (if (eq 'vertical-scroll-bar |
249 (nth 1 t-mouse-drag-start)) 'scroll-bar-movement | 225 (nth 1 t-mouse-drag-start)) 'scroll-bar-movement |
250 'mouse-movement) | 226 'mouse-movement) |
251 (t-mouse-make-event-element current-xy-avec-time)))))))) | 227 (t-mouse-make-event-element current-xy-avec-time)))))))) |
252 | 228 |
253 | |
254 (defun t-mouse-process-filter (proc string) | 229 (defun t-mouse-process-filter (proc string) |
255 (setq t-mouse-filter-accumulator | 230 (setq t-mouse-filter-accumulator |
256 (concat t-mouse-filter-accumulator string)) | 231 (concat t-mouse-filter-accumulator string)) |
257 (let ((event (t-mouse-make-event))) | 232 (let ((event (t-mouse-make-event))) |
258 (while event | 233 (while event |
262 (nconc unread-command-events (list event)))) | 237 (nconc unread-command-events (list event)))) |
263 (if t-mouse-debug-buffer | 238 (if t-mouse-debug-buffer |
264 (print unread-command-events t-mouse-debug-buffer)) | 239 (print unread-command-events t-mouse-debug-buffer)) |
265 (setq event (t-mouse-make-event))))) | 240 (setq event (t-mouse-make-event))))) |
266 | 241 |
267 | 242 (defun t-mouse-mouse-position-function (pos) |
268 ;; this overrides a C function which stupidly assumes (no X => no mouse) | |
269 (defadvice mouse-position (around t-mouse-mouse-position activate) | |
270 "Return the t-mouse-position unless running with a window system. | 243 "Return the t-mouse-position unless running with a window system. |
271 The (secret) scrollbar interface is not implemented yet." | 244 The (secret) scrollbar interface is not implemented yet." |
272 (if (not window-system) | 245 (setcdr pos t-mouse-current-xy) |
273 (setq ad-return-value | 246 pos) |
274 (cons (selected-frame) t-mouse-current-xy)) | |
275 ad-do-it)) | |
276 | |
277 (setq mouse-sel-set-selection-function | |
278 (function (lambda (type value) | |
279 (if (not window-system) | |
280 (if (eq 'PRIMARY type) (kill-new value)) | |
281 (funcall t-mouse-prev-set-selection-function | |
282 type value))))) | |
283 | |
284 (setq mouse-sel-get-selection-function | |
285 (function (lambda (type) | |
286 (if (not window-system) | |
287 (if (eq 'PRIMARY type) | |
288 (current-kill 0) "") | |
289 (funcall t-mouse-prev-get-selection-function type))))) | |
290 | 247 |
291 ;; It should be possible to just send SIGTSTP to the inferior with | 248 ;; It should be possible to just send SIGTSTP to the inferior with |
292 ;; stop-process. That doesn't work; mev receives the signal fine but | 249 ;; stop-process. That doesn't work; mev receives the signal fine but |
293 ;; is not really stopped: instead it returns from | 250 ;; is not really stopped: instead it returns from |
294 ;; kill(getpid(), SIGTSTP) immediately. I don't understand what's up | 251 ;; kill(getpid(), SIGTSTP) immediately. I don't understand what's up |
305 (function (lambda () | 262 (function (lambda () |
306 (and t-mouse-process | 263 (and t-mouse-process |
307 ;(continue-process t-mouse-process) | 264 ;(continue-process t-mouse-process) |
308 (process-send-string t-mouse-process "pop\n"))))) | 265 (process-send-string t-mouse-process "pop\n"))))) |
309 | 266 |
310 | 267 ;;;###autoload |
311 ;;; User commands | 268 (define-minor-mode t-mouse-mode |
312 | 269 "Toggle t-mouse mode. |
313 (defun t-mouse-stop () | 270 With prefix arg, turn t-mouse mode on iff arg is positive. |
314 "Stop getting mouse events from an asynchronous process." | 271 |
315 (interactive) | 272 Turn it on to use emacs mouse commands, and off to use t-mouse commands." |
316 (delete-process t-mouse-process) | 273 nil " Mouse" nil :global t |
317 (setq t-mouse-process nil)) | 274 (if t-mouse-mode |
318 | 275 ;; Turn it on |
319 (defun t-mouse-run () | 276 (unless window-system |
320 "Starts getting a stream of mouse events from an asynchronous process. | 277 ;; Starts getting a stream of mouse events from an asynchronous process. |
321 Only works if Emacs is running on a virtual terminal without a window system. | 278 ;; Only works if Emacs is running on a virtual terminal without a window system. |
322 Returns the newly created asynchronous process." | 279 (progn |
323 (interactive) | 280 (setq mouse-position-function #'t-mouse-mouse-position-function) |
324 (let ((tty (t-mouse-tty)) | 281 (let ((tty (t-mouse-tty)) |
325 (process-connection-type t)) | 282 (process-connection-type t)) |
326 (if (or window-system (not (stringp tty))) | 283 (if (not (stringp tty)) |
327 (error "Run t-mouse on a virtual terminal without a window system")) | 284 (error "Cannot find a virtual terminal.")) |
328 (setq t-mouse-process | 285 (setq t-mouse-process |
329 (start-process "t-mouse" nil | 286 (start-process "t-mouse" nil |
330 "mev" "-i" "-E" "-C" tty | 287 "mev" "-i" "-E" "-C" tty |
331 (if t-mouse-swap-alt-keys | 288 (if t-mouse-swap-alt-keys |
332 "-M-leftAlt" "-M-rightAlt") | 289 "-M-leftAlt" "-M-rightAlt") |
333 "-e-move" "-dall" "-d-hard" | 290 "-e-move" |
334 "-f"))) | 291 "-dall" "-d-hard" |
335 (setq t-mouse-filter-accumulator "") | 292 "-f"))) |
336 (set-process-filter t-mouse-process 't-mouse-process-filter) | 293 (setq t-mouse-filter-accumulator "") |
337 (process-kill-without-query t-mouse-process) | 294 (set-process-filter t-mouse-process 't-mouse-process-filter) |
338 t-mouse-process) | 295 ; use commented line instead for emacs 21.4 onwards |
296 (process-kill-without-query t-mouse-process))) | |
297 ; (set-process-query-on-exit-flag t-mouse-process nil))) | |
298 ;; Turn it off | |
299 (setq mouse-position-function nil) | |
300 (delete-process t-mouse-process) | |
301 (setq t-mouse-process nil))) | |
339 | 302 |
340 (provide 't-mouse) | 303 (provide 't-mouse) |
341 | 304 |
342 ;;; t-mouse.el ends here | 305 ;;; t-mouse.el ends here |