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