Mercurial > hg > xemacs
comparison shared/motion4.el @ 0:107d592c5f4a
DICE versions, used by pers/common, recursive, I think/hope
author | Henry S. Thompson <ht@inf.ed.ac.uk> |
---|---|
date | Mon, 08 Feb 2021 11:44:37 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:107d592c5f4a |
---|---|
1 ;;; Copyright (C) 1991 Christopher J. Love | |
2 ;;; | |
3 ;;; This file is for use with Epoch, a modified version of GNU Emacs. | |
4 ;;; Requires Epoch 4.0 or later. | |
5 ;;; | |
6 ;;; This code is distributed in the hope that it will be useful, | |
7 ;;; bute WITHOUT ANY WARRANTY. No author or distributor accepts | |
8 ;;; responsibility to anyone for the consequences of using this code | |
9 ;;; or for whether it serves any particular purpose or works at all, | |
10 ;;; unless explicitly stated in a written agreement. | |
11 ;;; | |
12 ;;; Everyone is granted permission to copy, modify and redistribute | |
13 ;;; this code, but only under the conditions described in the | |
14 ;;; GNU Emacs General Public License, except the original author nor his | |
15 ;;; agents are bound by the License in their use of this code. | |
16 ;;; (These special rights for the author in no way restrict the rights of | |
17 ;;; others given in the License or this prologue) | |
18 ;;; A copy of this license is supposed to have been given to you along | |
19 ;;; with Epoch so you can know your rights and responsibilities. | |
20 ;;; It should be in a file named COPYING. Among other things, the | |
21 ;;; copyright notice and this notice must be preserved on all copies. | |
22 ;;; | |
23 ;;; $Revision: 1.2 $ | |
24 ;;; $Source: /home/user5/ht/emacs/shared/RCS/motion4.el,v $ | |
25 ;;; $Date: 1992/03/18 21:44:10 $ | |
26 ;;; $Author: ht $ | |
27 ;;; | |
28 ;;; motion.el - provide draggin/hi-lighting of primary selection | |
29 ;;; | |
30 ;;; Original version by Alan Carroll | |
31 ;;; Epoch 4.0 modifications by Chris Love | |
32 ;;; Abort-isearch and other ideas from Ken Laprade and others. | |
33 ;;; | |
34 (provide 'motion) | |
35 (redisplay-screen) ; fix epoch4.0a race bug? | |
36 (require 'zone) | |
37 (require 'mouse) | |
38 | |
39 ;;; ------------------------------------------------------------------------ | |
40 ;;; Interface values | |
41 (defvar horizontal-drag-inc 5 | |
42 "Number of columns to scroll when the pointer is to the left or right of the window") | |
43 (defvar vertical-drag-inc 2 | |
44 "Number of lines to scroll when the pointer is above or below the edge of the window") | |
45 | |
46 (defvar mouse::downp nil "State variable for mouse dragging internals") | |
47 (defvar mouse::last-point -1 "Last location of a motion event") | |
48 | |
49 (setq epoch::zones-modify-buffer nil) | |
50 (defvar motion::style nil "style used by drag zones") | |
51 | |
52 (defvar drag-zone nil | |
53 "Epoch zone to be used for hilighting selected text region." | |
54 ) | |
55 (setq-default drag-zone nil) | |
56 (setq-default mouse-down-marker nil) | |
57 | |
58 ;;; ------------------------------------------------------------------------ | |
59 ;;; Set window-setup-hook to call motion::init(), which sets default | |
60 ;;; style for zone dragging. Default style is underlining; can be changed | |
61 ;;; in .emacs file. | |
62 (epoch-add-setup-hook 'motion::init) | |
63 | |
64 (defun motion::init () | |
65 (and (not motion::style) (setq motion::style (make-style))) | |
66 (set-style-foreground motion::style (foreground)) | |
67 (set-style-background motion::style (background)) | |
68 (set-style-underline motion::style (foreground)) | |
69 ;; enable the handler | |
70 (push-event 'motion 'motion::handler) | |
71 ;; set up hints on all the current screens | |
72 (dolist (s (screen-list t)) (epoch::set-motion-hints t s)) | |
73 ;; enable hints on future screens | |
74 (push '(motion-hints t) epoch::screen-properties) | |
75 ) | |
76 | |
77 ;;; ------------------------------------------------------------------------ | |
78 (defun set-mouse-marker (&optional location) | |
79 (if (null mouse-down-marker) | |
80 (setq mouse-down-marker (make-marker)) | |
81 ) | |
82 (set-marker mouse-down-marker (or location (point))) | |
83 ) | |
84 | |
85 ;;; -------------------------------------------------------------------------- | |
86 ;;; Functions to provide dragging & hilighting. | |
87 ;;; arg is a list of ( POINT BUFFER WINDOW SCREEN ) | |
88 (defun end-mouse-drag (arg) | |
89 (setq mouse::last-point -1) ;always do this cleanup | |
90 (when mouse::downp | |
91 (setq mouse::downp nil) | |
92 (mouse::copy-zone drag-zone) | |
93 (let ( | |
94 (s (and drag-zone (zone-start drag-zone))) | |
95 (e (and drag-zone (zone-end drag-zone))) | |
96 ) | |
97 (if (null s) (setq s 1)) | |
98 (if (null e) (setq e 1)) | |
99 (if (zonep drag-zone) | |
100 (if (<= (point) s) | |
101 (progn | |
102 (push-mark e t) | |
103 (goto-char s) | |
104 ) | |
105 ;; ELSE point is past drag zone start | |
106 (progn | |
107 (push-mark s t) | |
108 (goto-char e) | |
109 ) | |
110 ) | |
111 ) | |
112 ) | |
113 ) | |
114 ) | |
115 | |
116 (defun start-mouse-drag (arg) | |
117 (when arg | |
118 (setq mouse::downp 'start) | |
119 ; (message "%s" arg) | |
120 (mouse::set-point arg) | |
121 (abort-isearch) | |
122 (set-mouse-marker) | |
123 (setq mouse::last-point (point)) | |
124 (if drag-zone | |
125 (progn | |
126 (message "ddz") | |
127 (delete-zone drag-zone) | |
128 (setq drag-zone nil) | |
129 (redisplay-screen) | |
130 ) | |
131 ) | |
132 ) | |
133 ) | |
134 | |
135 (defun extend-mouse-drag (arg) | |
136 (setq mouse::downp 'extend) | |
137 (let | |
138 ( | |
139 (m1 (and drag-zone (zone-start drag-zone))) | |
140 (m2 (and drag-zone (zone-end drag-zone))) | |
141 (spot (car arg)) ;point of the mouse click. | |
142 ) | |
143 (if (null m1) (setq m1 0)) | |
144 (if (null m2) (setq m2 0)) | |
145 (cond | |
146 ((or (null drag-zone) (null mouse-down-marker)) | |
147 (setq drag-zone (add-zone (point) spot motion::style) ) | |
148 (set-zone-transient drag-zone t) | |
149 (set-mouse-marker) | |
150 ) | |
151 ((<= spot m1) | |
152 (setq drag-zone (move-zone drag-zone spot m2) ) | |
153 (set-mouse-marker m2) | |
154 ) | |
155 ((>= spot m2) | |
156 (setq drag-zone (move-zone drag-zone m1 spot) ) | |
157 (set-mouse-marker m1) | |
158 ) | |
159 ((<= mouse-down-marker spot) | |
160 (setq drag-zone (move-zone drag-zone m1 spot) ) | |
161 (set-mouse-marker m1) | |
162 ) | |
163 (t | |
164 (setq drag-zone (move-zone drag-zone spot m2) ) | |
165 (set-mouse-marker m2) | |
166 ) | |
167 ) | |
168 (epoch::redisplay-screen) | |
169 (setq mouse::last-point (point)) | |
170 ) | |
171 ) | |
172 | |
173 ;;; ------------------------------------------------------------------------ | |
174 ;;; Define the handler for dragging, etc. | |
175 (defun motion::handler (type value scr) | |
176 (if (null mouse-down-marker) (set-mouse-marker)) | |
177 (if (and (boundp 'mouse::downp) mouse::downp) | |
178 (mouse-sweep-update) | |
179 ) | |
180 ) | |
181 | |
182 ;;; | |
183 (defun mouse-sweep-update() | |
184 (let* | |
185 ( | |
186 drag-m1 | |
187 drag-m2 | |
188 pnt | |
189 pos | |
190 x | |
191 y | |
192 (w (selected-window)) | |
193 (out-of-bounds t) | |
194 (epoch::event-handler-abort nil) | |
195 (w-edges (window-pixedges w)) | |
196 (left (car w-edges)) | |
197 (top (elt w-edges 1)) | |
198 (right (- (elt w-edges 2) left 1)) | |
199 (bottom (- (elt w-edges 4) top 1)) | |
200 ) | |
201 (while | |
202 (and | |
203 out-of-bounds | |
204 (setq pos (query-pointer)) | |
205 (/= 0 (logand mouse-any-mask (elt pos 2))) | |
206 ) | |
207 ;;convert to window relative co-ordinates | |
208 (setq x (- (car pos) left)) | |
209 (setq y (- (elt pos 1) top)) | |
210 (setq out-of-bounds | |
211 (not (and (<= 0 y) (<= y bottom) (<= 0 x) (<= x right))) | |
212 ) | |
213 ;; scrolling conditions | |
214 (condition-case errno | |
215 (progn | |
216 (if (< y 0) (scroll-down vertical-drag-inc)) | |
217 (if (> y bottom) (scroll-up vertical-drag-inc)) | |
218 ) | |
219 (error ) ;nothing, just catch it | |
220 ) | |
221 ;; Disable horizontal scrolling. | |
222 ; (if (< x left) (scroll-right horizontal-drag-inc)) | |
223 ; (if (> x right) (scroll-left horizontal-drag-inc)) | |
224 (setq y (max 1 (min bottom y))) | |
225 (setq x (max 0 (min right x))) | |
226 (setq pnt (car (epoch::coords-to-point (+ x left) (+ y top)))) | |
227 (when (/= mouse::last-point pnt) | |
228 (if (> mouse-down-marker pnt) | |
229 (progn | |
230 (setq drag-m1 pnt) | |
231 (setq drag-m2 (marker-position mouse-down-marker)) | |
232 ) | |
233 (progn | |
234 (setq drag-m1 (marker-position mouse-down-marker)) | |
235 (setq drag-m2 (1+ pnt)) | |
236 ) | |
237 ) | |
238 ;; moved this in here so that zone won't get made if | |
239 ;; only motion is jitter within a single character | |
240 ;; this fixes a bunch of bogus (often empty) | |
241 ;; entries in the kill ring | |
242 (if drag-zone | |
243 (move-zone drag-zone drag-m1 drag-m2) | |
244 (progn (setq drag-zone | |
245 (add-zone drag-m1 drag-m2 motion::style ) | |
246 ) | |
247 (set-zone-transient drag-zone t) | |
248 ) | |
249 ) | |
250 (redisplay-screen) | |
251 ) | |
252 (setq mouse::last-point pnt) | |
253 ) | |
254 ) | |
255 ) | |
256 | |
257 ;;; ------------------------------------------------------------------------ | |
258 ;;; Code for selecting lines using motion events. Assumes that the line is | |
259 ;;; left unmarked on zone up | |
260 (defvar mouse::line-zone nil "Zone for selected line") | |
261 ;;; | |
262 (defun mouse-select-line-start (arg) | |
263 (mouse::set-point arg) ;go there | |
264 (setq mouse::last-point (point)) | |
265 (let ( bol ) | |
266 (save-excursion | |
267 (beginning-of-line) | |
268 (setq bol (point)) | |
269 (end-of-line) | |
270 (setq mouse::line-zone (add-zone bol (point) motion::style)) | |
271 ) | |
272 ) | |
273 (push-event 'motion 'mouse-select-line-update) | |
274 ) | |
275 ;;; | |
276 (defun mouse-select-line-end (arg) | |
277 (setq mouse::last-point -1) | |
278 (when mouse::line-zone (delete-zone mouse::line-zone)) | |
279 (pop-event 'motion) | |
280 ) | |
281 ;;; | |
282 (defun mouse-select-line-update (type value scr) | |
283 (let* | |
284 ( | |
285 y | |
286 pos | |
287 bol | |
288 (out-of-bounds t) | |
289 (epoch::event-handler-abort nil) | |
290 (w-edges (window-pixedges (selected-window))) | |
291 (top (elt w-edges 1)) | |
292 (bottom (- (elt w-edges 4) top 1)) | |
293 max-vscroll | |
294 ) | |
295 (while | |
296 (and | |
297 out-of-bounds | |
298 (setq pos (query-pointer)) | |
299 (/= 0 (logand mouse-any-mask (elt pos 2))) | |
300 ) | |
301 ;;convert to window relative co-ordinates | |
302 (setq y (- (elt pos 1) top)) | |
303 (setq out-of-bounds (not (and (<= 0 y) (<= y bottom)))) | |
304 | |
305 ;; Scrolling hard, because of possibly shrink-wrapped windows. | |
306 ;; set max-vscroll to be the most we could scroll down and not have | |
307 ;; empty lines at the bottom | |
308 (save-excursion | |
309 (move-to-window-line bottom) ;go to the last line in the window | |
310 (setq max-vscroll | |
311 (- vertical-drag-inc (forward-line vertical-drag-inc)) | |
312 ) | |
313 (if (and (> max-vscroll 0) (eobp) (= 0 (current-column))) | |
314 (decf max-vscroll) | |
315 ) | |
316 ) | |
317 (condition-case errno | |
318 (progn | |
319 (if (< y 0) (scroll-down vertical-drag-inc)) | |
320 (if (> y bottom) (scroll-up (min max-vscroll vertical-drag-inc))) | |
321 ) | |
322 ;; CONDITIONS | |
323 (error) ;nothing, just want to catch it | |
324 ) | |
325 (setq y (max 0 (min bottom y))) | |
326 | |
327 ;;move to the new point | |
328 (move-to-window-line y) | |
329 (beginning-of-line) (setq bol (point)) | |
330 (end-of-line) | |
331 (when (/= mouse::last-point (point)) | |
332 (move-zone mouse::line-zone bol (point)) | |
333 (epoch::redisplay-screen) | |
334 ) | |
335 (setq mouse::last-point (point)) | |
336 ) | |
337 ) | |
338 ) | |
339 ;;; -------------------------------------------------------------------------- | |
340 ;; Stolen from AMC | |
341 (defun mouse::buffer-line (marg) | |
342 "Show the line number and buffer of the mouse EVENT" | |
343 ;; marg is (point buffer window screen) | |
344 ;; Pop over to the clicked buffer | |
345 (save-excursion (set-buffer (cadr marg)) | |
346 ;; Figure out how far down the mouse point is | |
347 (let ((n (count-lines (point-min) (car marg)))) | |
348 ;; display it. Include the buffer name for good measure. | |
349 (message (format "Line %d in %s" n (buffer-name (cadr marg)))) | |
350 ))) | |
351 | |
352 ;; Blow out of any current isearch | |
353 (defun abort-isearch () "Abort any isearch in progress." | |
354 (condition-case err | |
355 (throw 'search-done t) | |
356 (no-catch nil))) | |
357 ;;; -------------------------------------------------------------------------- | |
358 ;;; install all our various handlers | |
359 (global-set-mouse mouse-left mouse-down 'start-mouse-drag) | |
360 (global-set-mouse mouse-left mouse-shift 'mouse::buffer-line) | |
361 (global-set-mouse mouse-left mouse-up 'end-mouse-drag) | |
362 (global-set-mouse mouse-right mouse-down 'extend-mouse-drag) | |
363 (global-set-mouse mouse-right mouse-up 'end-mouse-drag) | |
364 (global-set-mouse mouse-middle mouse-down 'mouse::paste-cut-buffer) | |
365 | |
366 | |
367 (defun mouse-set-spot (arg) | |
368 "Set point at mouse. With double-click, set mark there as well. | |
369 Blinks matching paren if sitting after one. Intended to be bound | |
370 to a window down button." | |
371 (start-mouse-drag arg) | |
372 (let ((buf (current-buffer)) | |
373 (p (point))) | |
374 (mouse::set-point arg) | |
375 (if (and (equal p (point)) | |
376 (equal buf (current-buffer))) | |
377 (if (and (= mouse::clicks 1) | |
378 (not (eq (mark) (point)))) | |
379 (push-mark)) | |
380 (setq mouse::clicks 0)) | |
381 (if (eq (char-syntax (preceding-char)) ?\)) | |
382 (blink-matching-open))) | |
383 (abort-isearch)) | |
384 | |
385 |