comparison lisp/avoid.el @ 7015:41b90d7dd228

doc fix. (mouse-avoidance-point-position): new function, using new `compute-motion' functionality. Use of this fixes bugs involving wrapped lines & horizontally-scrolled windows. new avoidance mode, "exile", like "banish" but temporary. jump/animate modes now keep track of net offset that they have moved the mouse, and try to keep this near 0. No longer wraps to other side of screen. (mouse-avoidance-mode): update mode line. (mouse-avoidance-*-hook): do nothing if inside kbd macro.
author Karl Heuer <kwzh@gnu.org>
date Thu, 21 Apr 1994 21:26:47 +0000
parents b8026de94b3a
children 48f98b59a339
comparison
equal deleted inserted replaced
7014:33e93a89fbe4 7015:41b90d7dd228
31 ;;; To set up permanently, put this file on your load-path and put the 31 ;;; To set up permanently, put this file on your load-path and put the
32 ;;; following in your .emacs: 32 ;;; following in your .emacs:
33 ;;; 33 ;;;
34 ;;; (cond (window-system 34 ;;; (cond (window-system
35 ;;; (require 'avoid) 35 ;;; (require 'avoid)
36 ;;; (mouse-avoidance-mode 'cat-and-mouse))) 36 ;;; (mouse-avoidance-mode 'animate)))
37 ;;; 37 ;;;
38 ;;; The 'cat-and-mouse can be 38 ;;; The 'animate can be 'jump or 'banish or 'exile or 'protean if you prefer.
39 ;;; 'banish or 'jump or 'animate or 'proteus if you prefer.
40 ;;; See the documentation for function `mouse-avoidance-mode' for 39 ;;; See the documentation for function `mouse-avoidance-mode' for
41 ;;; details of the different modes. 40 ;;; details of the different modes.
42 ;;; 41 ;;;
43 ;;; For added silliness, make the animatee animate... 42 ;;; For added silliness, make the animatee animate...
44 ;;; put something similar to the following into your .emacs: 43 ;;; put something similar to the following into your .emacs:
51 ;;; (set-mouse-color (cdr (assoc 'mouse-color (frame-parameters)))))) 50 ;;; (set-mouse-color (cdr (assoc 'mouse-color (frame-parameters))))))
52 ;;; 51 ;;;
53 ;;; For completely random pointer shape, replace the setq above with: 52 ;;; For completely random pointer shape, replace the setq above with:
54 ;;; (setq x-pointer-shape (mouse-avoidance-random-shape)) 53 ;;; (setq x-pointer-shape (mouse-avoidance-random-shape))
55 ;;; 54 ;;;
56 ;;; Bugs & Warnings: 55 ;;; Bugs / Warnings / To-Do:
57 ;;;
58 ;;; - Due to a bug in (mouse-position), this code can cause emacs
59 ;;; 19.22 to crash when deleting a frame if the mouse has not moved
60 ;;; since creating the frame. Versions earlier than 19.21 will
61 ;;; crash more easily; this program should not be used with them.
62 ;;; 56 ;;;
63 ;;; - Using this code does slow emacs down. "banish" mode shouldn't 57 ;;; - Using this code does slow emacs down. "banish" mode shouldn't
64 ;;; ever be too bad though, and on my workstation even "animate" doesn't 58 ;;; ever be too bad though, and on my workstation even "animate" doesn't
65 ;;; seem to have a noticable effect. 59 ;;; seem to have a noticable effect during editing.
66 ;;; 60 ;;;
67 ;;; - There are some situations where it doesn't do what you expect, 61 ;;; - It should find out where any overlapping frames are and avoid them,
68 ;;; notably when there are long wrapped lines in the buffer. Since 62 ;;; rather than always raising the frame.
69 ;;; there is no low-level command for finding point's position
70 ;;; on the screen, it can fail to move the pointer when on such a line.
71 63
72 ;;; Credits: 64 ;;; Credits:
73 ;;; This code was helped by all those who contributed suggestions, fixes, and 65 ;;; This code was helped by all those who contributed suggestions,
74 ;;; additions: 66 ;;; fixes, and additions
75 ;;; Joe Harrington (and his advisor), for the original inspiration 67 ;;; Joe Harrington (and his advisor), for the original inspiration.
76 ;;; Ken Manheimer, for dreaming up the Protean mode 68 ;;; Ken Manheimer, for dreaming up the Protean mode.
77 ;;; Richard Stallman, for the awful cat-and-mouse pun, among other things 69 ;;; Richard Stallman, for the awful cat-and-mouse pun, among other things.
78 ;;; Mike Williams, Denis Howe, Bill Benedetto, Chris Moore, Don Morris, 70 ;;; Mike Williams, Denis Howe, Bill Benedetto, Chris Moore, Don Morris,
79 ;;; Simon Marshall, and M.S. Ashton, for their feedback. 71 ;;; Simon Marshall, and M.S. Ashton, for their feedback.
80 ;;; 72 ;;;
81 ;;; Code: 73 ;;; Code:
82 74
86 "Value is t or a symbol if the mouse pointer should avoid the cursor. 78 "Value is t or a symbol if the mouse pointer should avoid the cursor.
87 See function mouse-avoidance-mode for possible values. Changing this 79 See function mouse-avoidance-mode for possible values. Changing this
88 variable is NOT the recommended way to change modes; use the function 80 variable is NOT the recommended way to change modes; use the function
89 instead.") 81 instead.")
90 82
91 (defvar mouse-avoidance-nudge-dist 4 83 (defvar mouse-avoidance-nudge-dist 15
92 "*Average distance that mouse will be moved when approached by cursor. 84 "*Average distance that mouse will be moved when approached by cursor.
93 Only applies in mode-avoidance-modes `animate' and `jump'.") 85 Only applies in mode-avoidance-mode and `jump' and its derivatives.
94 86 For best results make this larger than mouse-avoidance-threshhold.")
95 (defvar mouse-avoidance-nudge-var 3 87
88 (defvar mouse-avoidance-nudge-var 10
96 "*Variability of mouse-avoidance-nudge-dist (which see).") 89 "*Variability of mouse-avoidance-nudge-dist (which see).")
97 90
98 (defvar mouse-avoidance-animation-delay .01 91 (defvar mouse-avoidance-animation-delay .01
99 "Delay between animation steps, in seconds.") 92 "Delay between animation steps, in seconds.")
100 93
101 (defvar mouse-avoidance-threshhold 5 94 (defvar mouse-avoidance-threshhold 5
102 "*Mouse-pointer's flight distance. 95 "*Mouse-pointer's flight distance.
103 If the cursor gets closer than this, the mouse pointer will move away. 96 If the cursor gets closer than this, the mouse pointer will move away.
104 Only applies in mouse-avoidance-modes `animate' and `jump'.") 97 Only applies in mouse-avoidance-modes `animate' and `jump'.")
105 98
106 ;; Internal variables for mouse-avoidance-random-shape 99 ;; Internal variables
100 (defvar mouse-avoidance-state nil)
107 (defvar mouse-avoidance-pointer-shapes nil) 101 (defvar mouse-avoidance-pointer-shapes nil)
108 (defvar mouse-avoidance-n-pointer-shapes 0) 102 (defvar mouse-avoidance-n-pointer-shapes 0)
109 103
110 ;;; Functions: 104 ;;; Functions:
111 105
112 (defun mouse-avoidance-too-close-p () 106 (defun mouse-avoidance-point-position ()
107 "Return the position of point as (frame x . y).
108 Analogous to mouse-position."
109 (let* ((w (selected-window))
110 (edges (window-edges w))
111 (list
112 (compute-motion (window-start w) ; start pos
113 (cons (car edges) (car (cdr edges))) ; start XY
114 (point) ; stop pos
115 (cons (nth 2 edges) (nth 3 edges)) ; stop XY: none
116 (1- (window-width)) ; width
117 (cons (window-hscroll w) 0) ; 0 may not be right?
118 (selected-window))))
119 ;; compute-motion returns (pos HPOS VPOS prevhpos contin)
120 ;; we want: (frame hpos . vpos)
121 (setcar list (selected-frame))
122 (setcdr (cdr list) (car (cdr (cdr list))))
123 list))
124
125 (defun mouse-avoidance-set-mouse-position (pos)
126 ;; Carefully set mouse position to given position (X . Y)
127 ;; Ideally, should check if X,Y is in the current frame, and if not,
128 ;; leave the mouse where it was. However, this is currently
129 ;; difficult to do, so we just raise the frame to avoid frame switches.
130 ;; Returns t if it moved the mouse.
131 (let ((f (selected-frame)))
132 (raise-frame f)
133 (set-mouse-position f (car pos) (cdr pos))
134 t))
135
136 (defun mouse-avoidance-too-close-p (mouse)
113 ;; Return t if mouse pointer and point cursor are too close. 137 ;; Return t if mouse pointer and point cursor are too close.
114 ;; Acceptable distance is defined by mouse-avoidance-threshhold. 138 ;; Acceptable distance is defined by mouse-avoidance-threshhold.
115 (let ((mouse (mouse-position))) 139 (let ((point (mouse-avoidance-point-position)))
116 (and (car (cdr mouse)) 140 (and (eq (car mouse) (car point))
117 (< (abs (- (car (cdr mouse)) (current-column))) 141 (car (cdr mouse))
142 (< (abs (- (car (cdr mouse)) (car (cdr point))))
118 mouse-avoidance-threshhold) 143 mouse-avoidance-threshhold)
119 (< (abs (- (cdr (cdr mouse)) 144 (< (abs (- (cdr (cdr mouse)) (cdr (cdr point))))
120 (+ (car (cdr (window-edges)))
121 (count-lines (window-start) (point)))))
122 mouse-avoidance-threshhold)))) 145 mouse-avoidance-threshhold))))
146
147 (defun mouse-avoidance-banish-destination ()
148 "The position to which mouse-avoidance-mode 'banish moves the mouse.
149 You can redefine this if you want the mouse banished to a different corner."
150 (cons (1- (frame-width))
151 0))
123 152
124 (defun mouse-avoidance-banish-mouse () 153 (defun mouse-avoidance-banish-mouse ()
125 ;; Put the mouse pointer in the upper-right corner of the current frame. 154 ;; Put the mouse pointer in the upper-right corner of the current frame.
126 (set-mouse-position (selected-frame) (1- (frame-width)) 0)) 155 (mouse-avoidance-set-mouse-position (mouse-avoidance-banish-destination)))
156
157 (defsubst mouse-avoidance-delta (cur delta dist var min max)
158 ;; Decide how far to move in either dimension.
159 ;; Args are the CURRENT location, the desired DELTA for
160 ;; warp-conservation, the DISTANCE we like to move, the VARIABILITY
161 ;; in distance allowed, and the MIN and MAX possible window positions.
162 ;; Returns something as close to DELTA as possible withing the constraints.
163 (let ((L1 (max (- min cur) (+ (- dist) (- var))))
164 (R1 (+ (- dist) var ))
165 (L2 (+ dist (- var)))
166 (R2 (min (- max cur) (+ dist var))))
167 (if (< R1 (- min cur)) (setq L1 nil R1 nil))
168 (if (> L2 (- max cur)) (setq L2 nil R2 nil))
169 (cond ((and L1 (< delta L1)) L1)
170 ((and R1 (< delta R1)) delta)
171 ((and R1 (< delta 0)) R1)
172 ((and L2 (< delta L2)) L2)
173 ((and R2 (< delta R2)) delta)
174 (R2)
175 ((or R1 L2))
176 (t 0))))
127 177
128 (defun mouse-avoidance-nudge-mouse () 178 (defun mouse-avoidance-nudge-mouse ()
129 ;; Push the mouse a little way away, possibly animating the move 179 ;; Push the mouse a little way away, possibly animating the move
180 ;; For these modes, state keeps track of the total offset that we've
181 ;; accumulated, and tries to keep it close to zero.
130 (let* ((cur (mouse-position)) 182 (let* ((cur (mouse-position))
131 (deltax (* (+ mouse-avoidance-nudge-dist 183 (cur-frame (car cur))
132 (random mouse-avoidance-nudge-var)) 184 (cur-pos (cdr cur))
133 (if (zerop (random 2)) 1 -1))) 185 (deltax (mouse-avoidance-delta
134 (deltay (* (+ mouse-avoidance-nudge-dist 186 (car cur-pos) (- (random mouse-avoidance-nudge-var)
135 (random mouse-avoidance-nudge-var)) 187 (car mouse-avoidance-state))
136 (if (zerop (random 2)) 1 -1)))) 188 mouse-avoidance-nudge-dist mouse-avoidance-nudge-var
189 0 (frame-width)))
190 (deltay (mouse-avoidance-delta
191 (cdr cur-pos) (- (random mouse-avoidance-nudge-var)
192 (cdr mouse-avoidance-state))
193 mouse-avoidance-nudge-dist mouse-avoidance-nudge-var
194 0 (frame-height))))
195 (setq mouse-avoidance-state
196 (cons (+ (car mouse-avoidance-state) deltax)
197 (+ (cdr mouse-avoidance-state) deltay)))
137 (if (or (eq mouse-avoidance-mode 'animate) 198 (if (or (eq mouse-avoidance-mode 'animate)
138 (eq mouse-avoidance-mode 'proteus)) 199 (eq mouse-avoidance-mode 'proteus))
139 (let ((i 0.0) 200 (let ((i 0.0)
140 (color (cdr (assoc 'mouse-color (frame-parameters))))) 201 (color (cdr (assoc 'mouse-color (frame-parameters)))))
141 (while (<= i 1) 202 (while (<= i 1)
142 (set-mouse-position 203 (mouse-avoidance-set-mouse-position
143 (car cur) 204 (cons (+ (car cur-pos) (round (* i deltax)))
144 (mod (+ (car (cdr cur)) (round (* i deltax))) (frame-width)) 205 (+ (cdr cur-pos) (round (* i deltay)))))
145 (mod (+ (cdr (cdr cur)) (round (* i deltay))) (frame-height))) 206 (setq i (+ i (max .1 (/ 1.0 mouse-avoidance-nudge-dist))))
146 (setq i (+ i (/ 1.0 mouse-avoidance-nudge-dist)))
147 (if (eq mouse-avoidance-mode 'proteus) 207 (if (eq mouse-avoidance-mode 'proteus)
148 (progn 208 (progn
149 (setq x-pointer-shape (mouse-avoidance-random-shape)) 209 (setq x-pointer-shape (mouse-avoidance-random-shape))
150 (set-mouse-color color))) 210 (set-mouse-color color)))
151 (sit-for mouse-avoidance-animation-delay))) 211 (sit-for mouse-avoidance-animation-delay)))
152 (set-mouse-position 212 (mouse-avoidance-set-mouse-position
153 (car cur) 213 (cons (mod (+ (car (cdr cur)) deltax) (window-width))
154 (mod (+ (car (cdr cur)) deltax) (window-width)) 214 (mod (+ (cdr (cdr cur)) deltay) (window-height)))))))
155 (mod (+ (cdr (cdr cur)) deltay) (window-height))))))
156 215
157 (defun mouse-avoidance-random-shape () 216 (defun mouse-avoidance-random-shape ()
158 "Return a random cursor shape. 217 "Return a random cursor shape.
159 This assumes that any variable whose name begins with x-pointer- and 218 This assumes that any variable whose name begins with x-pointer- and
160 has an integer value is a valid cursor shape. You might want to 219 has an integer value is a valid cursor shape. You might want to
170 (setq mouse-avoidance-n-pointer-shapes 229 (setq mouse-avoidance-n-pointer-shapes
171 (length mouse-avoidance-pointer-shapes)))) 230 (length mouse-avoidance-pointer-shapes))))
172 (nth (random mouse-avoidance-n-pointer-shapes) 231 (nth (random mouse-avoidance-n-pointer-shapes)
173 mouse-avoidance-pointer-shapes)) 232 mouse-avoidance-pointer-shapes))
174 233
175 (defun mouse-avoidance-simple-hook () 234 (defun mouse-avoidance-banish-hook ()
176 (if (and (mouse-avoidance-keyboard-command (this-command-keys))) 235 (if (and (not executing-kbd-macro) ; don't check inside macro
177 (progn 236 (mouse-avoidance-kbd-command (this-command-keys)))
178 (raise-frame (selected-frame)) 237 (mouse-avoidance-banish-mouse)))
179 (mouse-avoidance-banish-mouse)))) 238
239 (defun mouse-avoidance-exile-hook ()
240 ;; For exile mode, the state is nil when the mouse is in its normal
241 ;; position, and set to the old mouse-position when the mouse is in exile.
242 (if (and (not executing-kbd-macro)
243 (mouse-avoidance-kbd-command (this-command-keys)))
244 (let ((mp (mouse-position)))
245 (cond ((and (not mouse-avoidance-state)
246 (mouse-avoidance-too-close-p mp))
247 (setq mouse-avoidance-state mp)
248 (mouse-avoidance-banish-mouse))
249 ((and mouse-avoidance-state
250 (not (mouse-avoidance-too-close-p mouse-avoidance-state)))
251 (if (and (eq (car mp) (selected-frame))
252 (equal (cdr mp) (mouse-avoidance-banish-destination)))
253 (mouse-avoidance-set-mouse-position
254 ;; move back only if user has not moved mouse
255 (cdr mouse-avoidance-state)))
256 ;; but clear state anyway, to be ready for another move
257 (setq mouse-avoidance-state nil))))))
180 258
181 (defun mouse-avoidance-fancy-hook () 259 (defun mouse-avoidance-fancy-hook ()
182 (if (and (mouse-avoidance-keyboard-command (this-command-keys)) 260 ;; Used for the "fancy" modes, ie jump et al.
183 (mouse-avoidance-too-close-p)) 261 (if (and (not executing-kbd-macro) ; don't check inside macro
262 (mouse-avoidance-kbd-command (this-command-keys))
263 (mouse-avoidance-too-close-p (mouse-position)))
184 (let ((old-pos (mouse-position))) 264 (let ((old-pos (mouse-position)))
185 (mouse-avoidance-nudge-mouse) 265 (mouse-avoidance-nudge-mouse)
186 (if (not (eq (selected-frame) (car old-pos))) 266 (if (not (eq (selected-frame) (car old-pos))) ; move went awry
187 (apply 'set-mouse-position old-pos))))) 267 (set-mouse-position old-pos (car old-pos) ; sigh..
188 268 (car (cdr old-pos))
189 (defun mouse-avoidance-keyboard-command (key) 269 (cdr (cdr old-pos)))))))
270
271 (defun mouse-avoidance-kbd-command (key)
190 "Return t if the KEYSEQENCE is composed of keyboard events only. 272 "Return t if the KEYSEQENCE is composed of keyboard events only.
191 Returns nil if there are any lists in the key sequence." 273 Returns nil if there are any lists in the key sequence."
192 (cond ((null key) nil) ; Null event seems to be 274 (cond ((null key) nil) ; Null event seems to be
193 ; returned occasionally. 275 ; returned occasionally.
194 ((not (vectorp key)) t) ; Strings are keyboard events. 276 ((not (vectorp key)) t) ; Strings are keyboard events.
201 (setq i (1+ i)))) 283 (setq i (1+ i))))
202 t)))) 284 t))))
203 285
204 (defun mouse-avoidance-mode (&optional mode) 286 (defun mouse-avoidance-mode (&optional mode)
205 "Set cursor avoidance mode to MODE. 287 "Set cursor avoidance mode to MODE.
206 MODE should be one of the symbols `banish', `jump', `animate', 288 MODE should be one of the symbols `banish', `exile', `jump', `animate',
207 `cat-and-mouse', `proteus', or `none'. 289 `cat-and-mouse', `proteus', or `none'.
208 290
209 If MODE is nil, toggle mouse avoidance between `none' and `banish' 291 If MODE is nil, toggle mouse avoidance between `none` and `banish'
210 modes. Positive numbers and symbols other than the above are treated 292 modes. Positive numbers and symbols other than the above are treated
211 as equivalent to `banish'; negative numbers and `-' are equivalent to `none'. 293 as equivalent to `banish'; negative numbers and `-' are equivalent to `none'.
212 294
213 Effects of the different modes: 295 Effects of the different modes:
214 * BANISH: Move the mouse to the upper-right corner on any keypress. 296 * BANISH: Move the mouse to the upper-right corner on any keypress.
215 Also raises the frame. 297 * EXILE: Move the mouse to the corner only if the cursor gets too close,
298 and allow it to return once the cursor is out of the way.
216 * JUMP: If the cursor gets too close to the mouse, displace the mouse 299 * JUMP: If the cursor gets too close to the mouse, displace the mouse
217 a random distance & direction. If this would put it in another, 300 a random distance & direction.
218 overlapping frame, it is put back \(until the next keypress).
219 * ANIMATE: As `jump', but shows steps along the way for illusion of motion. 301 * ANIMATE: As `jump', but shows steps along the way for illusion of motion.
220 * CAT-AND-MOUSE: Same as `animate'. 302 * CAT-AND-MOUSE: Same as `animate'.
221 * PROTEUS: As `animate', but changes the shape of the mouse pointer too. 303 * PROTEUS: As `animate', but changes the shape of the mouse pointer too.
304
305 Whenever the mouse is moved, the frame is also raised.
222 306
223 \(see `mouse-avoidance-threshhold' for definition of \"too close\", 307 \(see `mouse-avoidance-threshhold' for definition of \"too close\",
224 and `mouse-avoidance-nudge-dist' and `mouse-avoidance-nudge-var' for 308 and `mouse-avoidance-nudge-dist' and `mouse-avoidance-nudge-var' for
225 definition of \"random distance\".)" 309 definition of \"random distance\".)"
226 (interactive 310 (interactive
227 (list (intern (completing-read 311 (list (intern (completing-read
228 "Select cursor avoidance technique (SPACE for list): " 312 "Select cursor avoidance technique (SPACE for list): "
229 '(("banish") ("jump") ("animate") ("cat-and-mouse") 313 '(("banish") ("exile") ("jump") ("animate")
230 ("proteus") ("none")) 314 ("cat-and-mouse") ("proteus") ("none"))
231 nil t)))) 315 nil t))))
232 (if (eq mode 'cat-and-mouse) 316 (if (eq mode 'cat-and-mouse)
233 (setq mode 'animate)) 317 (setq mode 'animate))
234 (setq post-command-hook 318 (setq post-command-hook
235 (delete 'mouse-avoidance-simple-hook (append post-command-hook nil))) 319 (delete 'mouse-avoidance-banish-hook (append post-command-hook nil)))
320 (setq post-command-hook
321 (delete 'mouse-avoidance-exile-hook (append post-command-hook nil)))
236 (setq post-command-hook 322 (setq post-command-hook
237 (delete 'mouse-avoidance-fancy-hook (append post-command-hook nil))) 323 (delete 'mouse-avoidance-fancy-hook (append post-command-hook nil)))
238 (cond ((eq mode 'none) 324 (cond ((eq mode 'none)
239 (setq mouse-avoidance-mode nil)) 325 (setq mouse-avoidance-mode nil))
240 ((or (eq mode 'jump) 326 ((or (eq mode 'jump)
241 (eq mode 'animate) 327 (eq mode 'animate)
242 (eq mode 'proteus)) 328 (eq mode 'proteus))
243 (add-hook 'post-command-hook 'mouse-avoidance-fancy-hook) 329 (add-hook 'post-command-hook 'mouse-avoidance-fancy-hook)
244 (setq mouse-avoidance-mode mode)) 330 (setq mouse-avoidance-mode mode
331 mouse-avoidance-state (cons 0 0)))
332 ((eq mode 'exile)
333 (add-hook 'post-command-hook 'mouse-avoidance-exile-hook)
334 (setq mouse-avoidance-mode mode
335 mouse-avoidance-state nil))
245 ((or (eq mode 'banish) 336 ((or (eq mode 'banish)
246 (eq mode t) 337 (eq mode t)
247 (and (null mode) (null mouse-avoidance-mode)) 338 (and (null mode) (null mouse-avoidance-mode))
248 (and mode (> (prefix-numeric-value mode) 0))) 339 (and mode (> (prefix-numeric-value mode) 0)))
249 (add-hook 'post-command-hook 'mouse-avoidance-simple-hook) 340 (add-hook 'post-command-hook 'mouse-avoidance-banish-hook)
250 (setq mouse-avoidance-mode 'banish)) 341 (setq mouse-avoidance-mode 'banish))
251 (t (setq mouse-avoidance-mode nil)))) 342 (t (setq mouse-avoidance-mode nil)))
343 (force-mode-line-update))
252 344
253 (or (assq 'mouse-avoidance-mode minor-mode-alist) 345 (or (assq 'mouse-avoidance-mode minor-mode-alist)
254 (setq minor-mode-alist (cons '(mouse-avoidance-mode " Avoid") 346 (setq minor-mode-alist (cons '(mouse-avoidance-mode " Avoid")
255 minor-mode-alist))) 347 minor-mode-alist)))
256 348
257 ;;; End of avoid.el 349 ;;; End of avoid.el
258