diff shared/motion.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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/shared/motion.el	Mon Feb 08 11:44:37 2021 +0000
@@ -0,0 +1,319 @@
+;;; Copyright (C) 1990  Alan M. Carroll
+;;;
+;;; This file is for use with Epoch, a modified version of GNU Emacs.
+;;; Requires Epoch 3.2 or later.
+;;;
+;;; This code is distributed in the hope that it will be useful,
+;;; bute WITHOUT ANY WARRANTY. No author or distributor accepts
+;;; responsibility to anyone for the consequences of using this code
+;;; or for whether it serves any particular purpose or works at all,
+;;; unless explicitly stated in a written agreement.
+;;;
+;;; Everyone is granted permission to copy, modify and redistribute
+;;; this code, but only under the conditions described in the
+;;; GNU Emacs General Public License, except the original author nor his
+;;; agents are bound by the License in their use of this code.
+;;; (These special rights for the author in no way restrict the rights of
+;;;  others given in the License or this prologue)
+;;; A copy of this license is supposed to have been given to you along
+;;; with Epoch so you can know your rights and responsibilities. 
+;;; It should be in a file named COPYING.  Among other things, the
+;;; copyright notice and this notice must be preserved on all copies. 
+;;;
+(provide 'motion)
+(require 'button)
+(require 'mouse)
+;;;
+;;; version tohandle mouse stuff
+;;;
+;;; [cjl] now use primitive epoch::move-button when possible.
+;;;
+(defvar horizontal-drag-inc 5 "Number of columns to scroll when the pointer is to the left or right of the window")
+(defvar vertical-drag-inc 2 "Number of lines to scroll when the pointer is above or below the edge of the window")
+
+(defvar mouse::downp nil "State variable for mouse dragging internals")
+(defvar mouse::last-point -1 "Last location of a motion event")
+
+(make-variable-buffer-local 'drag-button)
+(make-variable-buffer-local 'mouse-down-marker)
+
+(defvar motion::attribute (reserve-attribute) "Attribute for drag buttons")
+(setq epoch::buttons-modify-buffer nil)
+
+(defvar motion::style nil "style used by drag buttons")
+
+;;
+;; Set window-setup-hook to call motion::init(), which sets default
+;; style for button dragging
+;;
+(epoch-add-setup-hook 'motion::init)
+(defun motion::init ()
+  (and (not motion::style) (setq motion::style (make-style)))
+  (set-style-foreground motion::style (foreground))
+  (set-style-background motion::style (background))
+  (set-style-underline motion::style (foreground))
+  (set-attribute-style motion::attribute motion::style)
+  ;; enable the handler
+  (push-event 'motion 'motion::handler)
+  ;; set up hints on all the current screens
+  (dolist (s (screen-list t)) (epoch::set-motion-hints t s))
+  ;; enable hints on future screens
+  (push '(motion-hints t) epoch::screen-properties)
+  )
+
+(setq-default drag-button nil)
+(setq-default mouse-down-marker nil)
+
+;;; ------------------------------------------------------------------------
+(defun set-mouse-marker (&optional location)
+  (if (null mouse-down-marker)
+    (setq mouse-down-marker (make-marker))
+  )
+  (set-marker mouse-down-marker (or location (point)))
+)
+;;; --------------------------------------------------------------------------
+;;; generic arg is a list of ( POINT BUFFER WINDOW SCREEN )
+;;;
+(defun end-mouse-drag (arg)
+  (setq mouse::last-point -1)		;always do this cleanup
+  (when mouse::downp
+    (setq mouse::downp nil)
+    (mouse::copy-button drag-button)
+    (if (buttonp drag-button)
+      (if (<= (point) (button-start drag-button))
+	(progn
+	  (push-mark (button-end drag-button) t)
+	  (goto-char (button-start drag-button))
+	)
+	;; ELSE point is past drag button start
+	(progn
+	  (push-mark (button-start drag-button) t)
+	  (goto-char (button-end drag-button))
+	)
+      )
+    )
+  )
+)
+
+(defun start-mouse-drag (arg)
+  (when arg
+    (setq mouse::downp 'start)
+    (mouse::set-point arg)
+    (set-mouse-marker)
+    (setq mouse::last-point (point))
+    (if drag-button
+      (progn (delete-button drag-button) (setq drag-button nil) )
+    )
+  )
+)
+
+(defun extend-mouse-drag (arg)
+  (setq mouse::downp 'extend)
+  (let
+    (
+      (m1 (and drag-button (button-start drag-button)))
+      (m2 (and drag-button (button-end drag-button)))
+      (spot (car arg))			;point of the mouse click.
+    )
+    (if (null m1) (setq m1 0))
+    (if (null m2) (setq m2 0))
+    (cond
+      ((or (null drag-button) (null mouse-down-marker))
+	(setq drag-button (add-button (point) spot motion::attribute) )
+	(set-mouse-marker)
+      )
+      ((<= spot m1)
+	(setq drag-button (move-button drag-button spot m2) )
+	(set-mouse-marker m2)
+      )
+      ((>= spot m2)
+	(setq drag-button (move-button drag-button m1 spot) )
+	(set-mouse-marker m1)
+      )
+      ((<= mouse-down-marker spot)
+	(setq drag-button (move-button drag-button m1 spot) )
+	(set-mouse-marker m1)
+      )
+      (t
+	(setq drag-button (move-button drag-button spot m2) )
+	(set-mouse-marker m2)
+      )
+    )
+    (epoch::redisplay-screen)
+    (setq mouse::last-point (point))
+  )
+)
+
+;;; ------------------------------------------------------------------------
+;;; Define the handler
+;;;
+(defun motion::handler (type value scr)
+  (if (null mouse-down-marker) (set-mouse-marker))
+  (if (and (boundp 'mouse::downp) mouse::downp)
+    (mouse-sweep-update)
+  )
+)
+;;;
+(defun mouse-sweep-update()
+  (let*
+    (x y pos drag-m1 drag-m2 pnt orig-m1 orig-m2
+      (out-of-bounds t)
+      (epoch::event-handler-abort nil)
+      (w (selected-window))
+      (w-edges (window-edges w))
+      (left (car w-edges))
+      (top (elt w-edges 1))
+      (right (- (elt w-edges 2) (+ 2 left)))
+      (bottom (- (elt w-edges 3) (+ 2 top)))
+      ever
+    )
+    (if drag-button
+	(progn (setq orig-m1 (or (button-start drag-button) -1))
+	       (setq orig-m2 (or (button-end drag-button) -1)))
+      (progn (setq orig-m1 mouse-down-marker)
+	     (setq orig-m2 (point))))
+    (while
+      (and
+	out-of-bounds
+	(setq pos (query-mouse))
+	(/= 0 (logand mouse-any-mask (elt pos 2)))
+      )
+      ;;convert to window relative co-ordinates
+      (setq x (- (car pos) left))
+      (setq y (- (elt pos 1) top))
+      (setq out-of-bounds
+	(not (and (<= 0 y) (<= y bottom) (<= 0 x) (<= x right)))
+      )
+
+      ;; scrolling conditions
+      (condition-case errno
+	(progn
+	  (if (< y 0) (scroll-down vertical-drag-inc))
+	  (if (> y bottom) (scroll-up vertical-drag-inc))
+	)
+	(error )			;nothing, just catch it
+      )
+      (if (< x 0) (scroll-right horizontal-drag-inc))
+      (if (> x right) (scroll-left horizontal-drag-inc))
+      (setq y (max 0 (min bottom y)))
+      (setq x (max 0 (min right x)))
+
+      (setq pnt (car (epoch::coords-to-point (+ x left) (+ y top))))
+      (when (/= mouse::last-point pnt)
+	    (if (> mouse-down-marker pnt)
+		(progn
+		  (setq drag-m1 pnt)
+		  (setq drag-m2 (marker-position mouse-down-marker))
+		  )
+	      (progn
+		(setq drag-m1 (marker-position mouse-down-marker))
+		(setq drag-m2 pnt)
+		)
+	      )
+	    ;; don't move for trivial reasons
+	    (when (or ever (/= drag-m1 orig-m1) (/= drag-m2 orig-m2))
+		  (setq ever t)
+		  (if (not drag-button)
+		      (setq drag-button
+			    (add-button mouse-down-marker
+					(point) motion::attribute )
+			    )
+		    )
+		  (move-button drag-button drag-m1 drag-m2)
+		  (epoch::redisplay-screen)
+		  )
+	    )
+      (setq mouse::last-point pnt)
+    )
+  )
+)
+;;; ------------------------------------------------------------------------
+;;; Code for selecting lines using motion events. Assumes that the line is
+;;; left unmarked on button up
+;;;
+(defvar mouse::line-button nil "Button for selected line")
+;;;
+(defun mouse-select-line-start (arg)
+  (mouse::set-point arg)		;go there
+  (setq mouse::last-point (point))
+  (let ( bol )
+    (save-excursion
+      (beginning-of-line)
+      (setq bol (point))
+      (end-of-line)
+      (setq mouse::line-button (add-button bol (point) motion::attribute))
+    )
+  )
+  (push-event 'motion 'mouse-select-line-update)
+)
+;;;
+(defun mouse-select-line-end (arg)
+  (setq mouse::last-point -1)
+  (when mouse::line-button (delete-button mouse::line-button))
+  (pop-event 'motion)
+)
+;;;
+(defun mouse-select-line-update (type value scr)
+  (let*
+    (
+      y
+      pos
+      bol
+      (out-of-bounds t)
+      (epoch::event-handler-abort nil)
+      (w-edges (window-edges (selected-window)))
+      (top (elt w-edges 1))
+      (bottom (- (elt w-edges 3) (+ 2 top)))
+      max-vscroll
+    )
+    (while
+      (and
+	out-of-bounds
+	(setq pos (query-mouse))
+	(/= 0 (logand mouse-any-mask (elt pos 2)))
+      )
+      ;;convert to window relative co-ordinates
+      (setq y (- (elt pos 1) top))
+      (setq out-of-bounds (not (and (<= 0 y) (<= y bottom))))
+
+      ;; Scrolling hard, because of possibly shrink-wrapped windows.
+      ;; set max-vscroll to be the most we could scroll down and not have
+      ;; empty lines at the bottom
+      (save-excursion
+	(move-to-window-line bottom)	;go to the last line in the window
+	(setq max-vscroll
+	  (- vertical-drag-inc (forward-line vertical-drag-inc))
+	)
+	(if (and (> max-vscroll 0) (eobp) (= 0 (current-column)))
+	  (decf max-vscroll)
+	)
+      )
+      (condition-case errno
+	(progn
+	  (if (< y 0) (scroll-down vertical-drag-inc))
+	  (if (> y bottom) (scroll-up (min max-vscroll vertical-drag-inc)))
+	)
+	;; CONDITIONS
+	(error)				;nothing, just want to catch it
+      )
+      (setq y (max 0 (min bottom y)))
+
+      ;;move to the new point
+      (move-to-window-line y)
+      (beginning-of-line) (setq bol (point))
+      (end-of-line)
+      (when (/= mouse::last-point (point))
+	(move-button mouse::line-button bol (point))
+	(epoch::redisplay-screen)
+      )
+      (setq mouse::last-point (point))
+    )
+  )
+)
+;;; --------------------------------------------------------------------------
+;;; install all our variouse handlers
+(global-set-mouse mouse-left mouse-down 'start-mouse-drag)
+(global-set-mouse mouse-left mouse-up 'end-mouse-drag)
+(global-set-mouse mouse-right mouse-down 'extend-mouse-drag)
+(global-set-mouse mouse-right mouse-up 'end-mouse-drag)
+(global-set-mouse mouse-middle mouse-down 'mouse::paste-cut-buffer)