diff lisp/hyperbole/hmouse-key.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 4103f0995bd7
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/hyperbole/hmouse-key.el	Mon Aug 13 08:45:50 2007 +0200
@@ -0,0 +1,348 @@
+;;!emacs
+;;
+;; FILE:         hmouse-key.el
+;; SUMMARY:      Load "hmouse-sh.el" or "hmouse-reg.el" for Smart Key bindings.
+;; USAGE:        GNU Emacs Lisp Library
+;; KEYWORDS:     hypermedia, mouse
+;;
+;; AUTHOR:       Bob Weiner
+;; ORG:          Motorola, Inc., PPG
+;;
+;; ORIG-DATE:    30-May-94 at 00:11:57
+;; LAST-MOD:     14-Sep-95 at 18:35:17 by Bob Weiner
+;;
+;; This file is part of Hyperbole.
+;; Available for use and distribution under the same terms as GNU Emacs.
+;;
+;; Copyright (C) 1994-1995, Free Software Foundation, Inc.
+;; Developed with support from Motorola Inc.
+;;
+;; DESCRIPTION:  
+;;
+;;   Supports Epoch, Lucid Emacs, X, Sunview, NEXTSTEP, and Apollo DM
+;;   window systems.
+;;
+;;   'hmouse-shift-buttons' globally binds the Action and Assist Mouse Keys
+;;   to either shifted or unshifted mouse buttons.
+;;
+;;   'hmouse-toggle-bindings' may be bound to a key.  It switches between
+;;   the Hyperbole mouse bindings and previous mouse key bindings any time
+;;   after 'hmouse-shift-buttons' has been called.
+;;
+;; DESCRIP-END.
+
+;;; ************************************************************************
+;;; Other required Elisp libraries
+;;; ************************************************************************
+
+(require 'hversion)
+(require 'hmouse-drv)
+(require 'h-skip-bytec "h-skip-bytec.lsp")
+
+;;; ************************************************************************
+;;; Public variables
+;;; ************************************************************************
+
+(eval (cdr (assoc hyperb:window-system
+		  '(
+		    ;; XEmacs and Emacs 19 pre-load their mouse libraries, so
+		    ;; we shouldn't have to require them here.
+		    ;;
+		    ("xterm"   . (require 'x-mouse))     ; X
+		    ("epoch"   . (require 'mouse))       ; UofI Epoch
+		    ("next"    . (load "eterm-fns" t))   ; NeXTstep
+		    ("sun"     . (require 'sun-fns))     ; SunView
+		    ("apollo"  . (require 'apollo))      ; Display Manager
+		    ))))
+
+;;; ************************************************************************
+;;; Public functions
+;;; ************************************************************************
+
+(defun hmouse-set-bindings (key-binding-list)
+  "Sets mouse keys used as Smart Keys to bindings in KEY-BINDING-LIST.
+KEY-BINDING-LIST is the value returned by 'hmouse-get-bindings' prior to
+Smart Key setup."
+  (cond
+    ;;
+    ;; GNU Emacs 19, Lucid Emacs, XEmacs or InfoDock
+    ((or (if (not noninteractive) (or hyperb:xemacs-p hyperb:emacs19-p))
+	 (equal hyperb:window-system "lemacs"))
+     (mapcar
+       (function
+	 (lambda (key-and-binding)
+	  (global-set-key (car key-and-binding) (cdr key-and-binding))))
+       key-binding-list))
+    ;;
+    ;; X
+    ((equal hyperb:window-system "xterm")
+     (mapcar
+       (function
+	 (lambda (key-and-binding)
+	   (define-key mouse-map (car key-and-binding) (cdr key-and-binding))))
+       key-binding-list))
+    ;;
+    ;; Epoch
+    ((equal hyperb:window-system "epoch")
+     (mapcar
+       (function
+	 (lambda (key-and-binding)
+	  (aset mouse::global-map (car key-and-binding)
+		(cdr key-and-binding))))
+       key-binding-list))
+    ;;
+    ;; SunView or NeXT
+    ((or (equal hyperb:window-system "next")
+	 (equal hyperb:window-system "sun"))
+     (mapcar
+       (function
+	 (lambda (key-and-binding)
+	   (global-set-mouse (car key-and-binding) (cdr key-and-binding))))
+       key-binding-list))
+    ;;
+    ;; Apollo Display Manager
+    ((equal hyperb:window-system "apollo")
+      (if (string< emacs-version "18.58")
+	  (mapcar
+	    (function
+	      (lambda (key-and-binding)
+		(global-set-key (car key-and-binding) (cdr key-and-binding))))
+	    key-binding-list)
+	(mapcar
+	  (function
+	    (lambda (key-and-binding)
+	      (define-key 'apollo-prefix (car key-and-binding)
+		(cdr key-and-binding)))) 
+	  key-binding-list)))))
+
+(defun hmouse-shift-buttons (&optional arg)
+  "Selects between shifted and unshifted Action and Assist mouse buttons.
+With optional prefix ARG, use shifted buttons if ARG is positive or use
+unshifted buttons otherwise.  If ARG is nil, shifted buttons are used and
+under InfoDock the middle button also acts as an Action Key."
+  (interactive "P")
+  (setq hmouse-shift-flag (if arg
+			      (> (prefix-numeric-value arg) 0)
+			    (not (and (boundp 'infodock-version)
+				      infodock-version))))
+  (if hmouse-shift-flag
+      ;; Action Key = shift-middle mouse key.  Assist Key = shift-right mouse
+      ;; key.  Standard Hyperbole configuration.
+      (load "hmouse-sh")
+    ;; Action Key = middle mouse key; Assist Key = right mouse key
+    ;; InfoDock actually moves the Assist Key to the shift-right mouse key so
+    ;; that the right key can be used for popup menus.
+    (load "hmouse-reg"))
+  ;; Replace any original mouse bindings before moving Hyperbole bindings and
+  ;; then force reinitialization of hmouse-previous-bindings.
+  (if (and hmouse-bindings-flag hmouse-previous-bindings)
+      (hmouse-set-bindings hmouse-previous-bindings))
+  (setq hmouse-bindings-flag nil
+	hmouse-previous-bindings nil)
+  ;; Initialize Hyperbole mouse bindings.
+  (hmouse-setup)
+  (if (interactive-p)
+      (message "%s Action and Assist mouse buttons in use."
+	       (if hmouse-shift-flag "Shifted" "Unshifted"))))
+
+(defun hmouse-toggle-bindings ()
+  "Toggles between Smart Key mouse settings and their prior bindings."
+  (interactive)
+  (let ((key-binding-list (if hmouse-bindings-flag
+			      hmouse-previous-bindings
+			    hmouse-bindings))
+	(other-list-var (if hmouse-bindings-flag
+			    'hmouse-bindings
+			  'hmouse-previous-bindings)))
+    (if key-binding-list
+	(progn
+	  (set other-list-var (hmouse-get-bindings))
+	  (hmouse-set-bindings key-binding-list)
+	  (message "%s mouse bindings in use."
+		   (if (setq hmouse-bindings-flag (not hmouse-bindings-flag))
+		       "Smart Key" "Personal")))
+      (error "(hmouse-toggle-bindings): Null %s." other-list-var))))
+
+(defun hmouse-set-point-at (set-point-arg-list)
+  "Sets point to cursor position using SET-POINT-ARG-LIST and returns t.
+If 'hmouse-set-point-command' is not bound to a function, this does nothing
+and returns nil."
+  (if (fboundp hmouse-set-point-command)
+      (progn
+	(if (and (boundp 'drag-zone) drag-zone)
+	    (progn (delete-zone drag-zone)
+		   (setq drag-zone nil))
+	  (and (boundp 'drag-button) drag-button
+	       (progn (delete-button drag-button)
+		      (setq drag-button nil))))
+	(or (if set-point-arg-list
+		(funcall hmouse-set-point-command set-point-arg-list)
+	      (funcall hmouse-set-point-command))
+	    t))))
+
+;;; ************************************************************************
+;;; Private functions
+;;; ************************************************************************
+
+(if (fboundp 'bind-apollo-mouse-button)
+    (progn
+      (if (string< emacs-version "18.58")
+	  (defun apollo-mouse-key-and-binding (mouse-button)
+	    "Returns binding for an Apollo MOUSE-BUTTON (a string) or nil if none."
+	    (interactive "sMouse Button: ")
+	    (let ((numeric-code (cdr (assoc mouse-button *apollo-mouse-buttons*))))
+	      (if (null numeric-code)
+		  (error "(hmouse-key): %s is not a valid Apollo mouse key name."
+			 mouse-button))
+	      (if (stringp numeric-code)
+		  (setq numeric-code
+			(cdr (assoc numeric-code *apollo-mouse-buttons*))))
+	      (let ((key-sequence (concat "\M-*" (char-to-string numeric-code))))
+		(cons key-sequence (global-key-binding key-sequence)))))
+	(defun apollo-mouse-key-and-binding (mouse-button)
+	  "Returns binding for an Apollo MOUSE-BUTTON (a string) or nil if none."
+	  (interactive "sMouse Button: ")
+	  (let ((numeric-code (cdr (assoc mouse-button *apollo-mouse-buttons*))))
+	    (if (null numeric-code)
+		(error "(hmouse-key): %s is not a valid Apollo mouse key name."
+		       mouse-button))
+	    (if (stringp numeric-code)
+		(setq numeric-code
+		      (cdr (assoc numeric-code *apollo-mouse-buttons*))))
+	    (let ((key-sequence (char-to-string numeric-code)))
+	      (cons key-sequence (lookup-key 'apollo-prefix key-sequence)))))
+	)
+      (defun apollo-mouse-move-point (&optional no-mark)
+	"Used so that pressing the left mouse button, moving the cursor, and
+releasing the left mouse button leaves the mark set to the initial position
+and the point set to the final position.  Useful for easily marking regions
+of text.  If the left mouse button is pressed and released at the same place,
+the mark is left at the original position of the character cursor.
+
+Returns (x y) frame coordinates of point in columns and lines."
+	(interactive)
+	(let* ((opoint (point))
+	       (owindow (selected-window))
+	       (x (- (read-char) 8))
+	       (y (- (read-char) 8))
+	       (edges (window-edges))
+	       (window nil))
+	  (while (and (not (eq window (selected-window)))
+		      (or (<  y (nth 1 edges))
+			  (>= y (nth 3 edges))
+			  (<  x (nth 0 edges))
+			  (>= x (nth 2 edges))))
+	    (setq window (next-window window))
+	    (setq edges (window-edges window)))
+	  (if (and window (not (eq window (selected-window))))
+	      (progn
+		(if (and (not *apollo-mouse-move-point-allow-minibuffer-exit*)
+			 (eq (selected-window) (minibuffer-window)))
+		    (error "Cannot use mouse to leave minibuffer!"))
+		(if (eq window (minibuffer-window))
+		    (error "Cannot use mouse to enter minibuffer!"))))
+	  (if window (select-window window))
+	  (move-to-window-line (- y (nth 1 edges)))
+	  (let* ((width-1 (1- (window-width window)))
+		 (wraps (/ (current-column) width-1))
+		 (prompt-length (if (eq (selected-window) (minibuffer-window))
+				    (minibuffer-prompt-length)
+				  0)))
+	    (move-to-column (+ (- x (nth 0 edges) prompt-length)
+			       (* wraps width-1))))
+	  (if no-mark
+	      (progn (setq window (selected-window))
+		     (if (eq owindow window)
+			 (if (equal opoint (point))
+			     (pop-mark))
+		       (select-window owindow)
+		       (pop-mark)
+		       (select-window window)))
+	    (set-mark-command nil))
+	  ;; Return (x y) coords of point in column and frame line numbers.
+	  (list x y)))
+      ))
+
+(defun action-key-depress (&rest args)
+  (interactive)
+  (require 'hsite)
+  (setq action-key-depress-prev-point (point-marker)
+	action-key-depressed-flag t
+	action-key-depress-args (hmouse-set-point args)
+	action-key-depress-window (selected-window)
+	action-key-release-args nil
+	action-key-release-window nil
+	action-key-release-prev-point nil)
+  (if assist-key-depressed-flag
+      (or action-key-help-flag
+	  (setq assist-key-help-flag t))))
+
+(defun assist-key-depress (&rest args)
+  (interactive)
+  (require 'hsite)
+  (setq assist-key-depress-prev-point (point-marker)
+	assist-key-depressed-flag t
+	assist-key-depress-args (hmouse-set-point args)
+	assist-key-depress-window (selected-window)
+	assist-key-release-args nil
+	assist-key-release-window nil
+	assist-key-release-prev-point nil)
+  (if action-key-depressed-flag
+      (or assist-key-help-flag
+	  (setq action-key-help-flag t)))
+  )
+
+(defun action-key-depress-emacs19 (event)
+  (interactive "e")
+  (require 'hsite)
+  (action-key-depress event))
+
+(defun assist-key-depress-emacs19 (event)
+  (interactive "e")
+  (require 'hsite)
+  (assist-key-depress event))
+
+(defun action-mouse-key-emacs19 (event)
+  "Set point to the current mouse cursor position and execute 'action-key'.
+EVENT will be passed to 'hmouse-function'."
+  (interactive "e")
+  (action-mouse-key (hmouse-key-release-args-emacs19 event)))
+
+(defun assist-mouse-key-emacs19 (event)
+  "Set point to the current mouse cursor position and execute 'action-key'.
+EVENT will be passed to 'hmouse-function'."
+  (interactive "e")
+  (assist-mouse-key (hmouse-key-release-args-emacs19 event)))
+
+(defun hmouse-key-release-args-emacs19 (event)
+  (let ((ev-type-str (and (listp event) (symbol-name (car event)))))
+    (if (or (and ev-type-str
+		 (string-match "\\(double\\|triple\\)-mouse" ev-type-str))
+	    (not (= (length event) 3)))
+	event
+      ;; Remove depress coordinates and send only release coordinates.
+      (list (car event) (nth 2 event)))))
+
+(defun hmouse-move-point-xemacs ()
+  (condition-case ()
+      (mouse-set-point current-mouse-event)
+    ;; Catch "not in a window" errors, e.g. on modeline
+    (error nil)))
+
+(defun hmouse-move-point-eterm (arg-list)
+  (apply 'mouse-move-point arg-list))
+
+;;; ************************************************************************
+;;; Private variables
+;;; ************************************************************************
+
+(defvar hmouse-bindings nil
+  "List of (key . binding) pairs for Smart Mouse Keys.")
+
+(defvar hmouse-bindings-flag nil
+  "True if Smart Key mouse bindings are in use, else nil.")
+
+(defvar hmouse-previous-bindings nil
+  "List of previous (key . binding) pairs for mouse keys used as Smart Keys.")
+
+(provide 'hmouse-key)