diff lisp/packages/mode-motion+.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children ac2d302a0011
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/packages/mode-motion+.el	Mon Aug 13 08:45:50 2007 +0200
@@ -0,0 +1,2214 @@
+;;   -*- Syntax: Emacs-Lisp; Mode: emacs-lisp -*-
+;;
+;; Per mode and per buffer mouse tracking with highlighting
+;;
+;; Copyright (C) 1992, 1993 by Guido Bosch <Guido.Bosch@loria.fr>
+
+;; This file is written in GNU Emacs Lisp, It is a part of XEmacs.
+
+;; The software contained in this file is free software; you can
+;; redistribute it and/or modify it under the terms of the GNU General
+;; Public License as published by the Free Software Foundation; either
+;; version 2, or (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;;
+;;; Synched up with: Not in FSF.
+
+;; Please send bugs and comments to Russell.Ritchie@gssec.bt.co.uk or
+;;                                  tlp00@spg.amdahl.com.
+;;
+;; <DISCLAIMER>
+;; This program is still under development.  Neither the author nor any
+;; of the maintainers accepts responsibility to anyone for the consequences of
+;; using it or for whether it serves any particular purpose or works
+;; at all.
+
+; Change History
+; Revision 3.15 Thu Feb 15 14:26:34 GMT 1996 Russell.Ritchie@gssec.bt.co.uk
+; lisp-interaction-popup-menu => lisp-interaction-mode-popup-menu,
+; emacs-lisp-popup-menu => emacs-lisp-mode-popup-menu.
+
+; Revision 3.14 Tue Nov 14 11:14:38 GMT 1995 Russell.Ritchie@gssec.bt.co.uk
+; Made nil the default value for mode-motion-focus-on-window.  Too many people
+; hate it when the cursor warps into Dired and GNUS buffers because some
+; window managers auto-raise the window with keyboard focus with predictably
+; nauseous results.
+
+; Revision 3.13 Thu Sep 14 10:30:04 1995 Russell.Ritchie@gssec.bt.co.uk
+; Fix the `spontaneous scrolling' problem (at last).  It's funny how
+; easy things are once you actually understand the issues involved.
+; As ever, what we sought was the right question...
+
+; Revision 3.12 Wed Jul 12 11:30:43 1995 Russell.Ritchie@gssec.bt.co.uk
+; Track `don't highlight non-file lines in dired buffers' functionality (in a
+; pretty tasteless manner if I say so myself :-)).
+
+; Revision 3.11 Fri Jul  7 16:26:56 1995 Russell.Ritchie@gssec.bt.co.uk
+; Minor extent detaching bug fix.
+
+; Revision 3.10 Thu Jun 15 11:36:56 1995 Russell.Ritchie@gssec.bt.co.uk
+; Quiet, faster, non-interactive initialistion, mild list-motion-handlers
+; chrome and minor formatting clean-ups.
+
+; Revision 3.9 Thu Jun 15 11:36:56 1995 Russell.Ritchie@gssec.bt.co.uk
+; Fixed the `mouse-motion whilst reading filename in minibuffer auto-ftp' bug.
+
+; Revision 3.8 Thus Mar 23 1995 tlp00@spg.amdahl.com
+; added in menu controls from paquette@atomas.crim.ca
+; re-added minibuffer support (from 3.5)
+;
+; Revision 3.7 Tue Feb 21 11:06:38 1995 Russell.Ritchie@gssec.bt.co.uk
+; Extended mode-motion+-religion and made the defaulting frame-buffer aware.
+; Reworked and added new mode-motion-handlers.
+; Doc string clean up.
+; Fixed unintentional frame/screen reversion.
+
+; Revision 3.6 Mon Feb 20 11:46:32 1995 Russell.Ritchie@gssec.bt.co.uk
+; Made mouse tracking use mode-motion-hook for better integration with
+; the default mouse-motion system (help-echo and friends now work).
+
+; Revision 3.5 1995/02/16 13:40:00 tlp00@spg.amdahl.com
+; fixed sporatic scroll bug
+; added M-button2 binding for mode-motion-copy
+;
+; Revision 3.4 1995/02/14 14:30:15 Russell.Ritchie@gssec.bt.co.uk
+; Small code cleanups: let* -> let, duplicate defvars.
+; Chromed list-motion-handlers a little.
+; Added variable mode-motion+-religion for easy choice twixt underline & bold.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;tlp00 changes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; tlp00@spg.amdahl.com 2/11/93
+; modified mode-motion-track-pointer to move cursor cross windows
+;          renamed mode-motion-delete to mode-motion-kill to follow kill
+;            convention
+;          mode-motion-highlight-with-handler to put cursor at beginning of line 
+;            follow operations.
+;          mode-motion-copy/delete and mode-motion-kill to position cursor at 
+;            delete point start.  Also set this-command to avoid appends
+; set mode-motion-extent priority to 1, so it will override font-lock
+; changed default handlers for buffer-mode, c-mode, dired-mode, added occur 
+;   and compilation mode.
+; fixed bug in minibuffer-selection-boundaries where C-g was leaving the wrong
+;   syntax table.
+; added support for pending-delete.
+; adds the copy/delete motion-extent to the clipboard even if kill-hooks is nil.
+;
+; Revision 3.3 1995/02/13 tlp00@spg.amdahl.com
+; merged Russell.Ritchie@gssec.bt.co.uk versions with molli/bosch versions
+; renamed versioning 3.0+ for molli/bosch versions.  
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Russell Ritchie changes;;;;;;;;;;;;;;;;;;;;;;;;
+; !Log: mode-motion+.el,v !
+; Revision 2.14.R  1994/09/09  10:19:18  rieke@darmstadt.gmd.de
+; Merged in my changes to support motion-gray. This needs a file
+; named "gray1.xbm" in your data-directory (etc) like the following.
+; -------------------------------snip--------------------------
+; #define bg2_width 16
+; #define bg2_height 16
+; static char bg2_bits[] = {
+;   0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,
+;   0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,
+;   0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00};
+; -------------------------------snip--------------------------
+; This one looks good on SUN 19'' screens with 10x20 font, 
+; black foreground and khaki background. 
+; To use the gray-handlers instead of the underline-handlers
+; include the following into your .emacs:
+; (set-mode-motion-handler 'emacs-lisp-mode 'gray-thing)
+; (set-mode-motion-handler 'lisp-interaction-mode 'gray-thing)
+; (set-mode-motion-handler 'c++-mode 'gray-c)
+; (set-mode-motion-handler 'c-mode 'gray-c)
+; (set-mode-motion-handler 'tcl-mode 'gray-tcl)
+; (set-mode-motion-handler 'dired-mode 'gray-line@)
+; (set-mode-motion-handler 'gnus-group-mode 'gray-vline@)
+; (set-mode-motion-handler 'gnus-summary-mode 'gray-vline@)
+; (set-mode-motion-handler 'texinfo-mode 'gray-Texinfo)
+; (setq default-motion-handler (find-motion-handler 'gray-thing))
+;
+;
+; Revision 2.13.R  1994/08/08  19:47:34  Russell.Ritchie@gssec.bt.co.uk
+; Made default handler be underline-thing, as most bold fonts seem to
+; be greater in height than their corresponding normal versions,
+; causing irritating screen flicker.
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Molli/bosch changes;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; Revision 3.2  1994/09/28  15:14:29  molli
+; add   "(set-mode-motion-handler 'latex-mode   'raise-LaTeX)".    Barry
+; Waraw's C/C++ mode is now changed to cc-mode ...
+;
+; Revision 3.1  1994/09/28  15:10:36  molli
+; Initial revision
+;
+; Revision 2.15  1993/11/18  08:13:28  bosch
+; Constant `mode-motion+-version' added.
+; Minor bug fix in `tcl-forward-sexp1'.
+;
+; Revision 2.14  1993/10/29  20:04:59  bosch
+; Minibuffer name matching improved.  Made `tcl-boundaries' smarter by
+; use of new function `tcl-forward-sexp1'. `tcl-commands' list updated
+; -- should be complete now.  A message is printed if the syntax scanner
+; matched or failed for known tcl/tk commands.  Seperated `tcl-commands'
+; from `tk-commands' -- `tk-commands' not yet complete.  New motion
+; handler `raise-LaTeX' added, for tex-mode.
+;
+; Revision 2.13  1993/10/08  09:43:00  bosch
+; New user option `mode-motion-setup-cut-and-paste-bindings'.  Function
+; `mode-motion-copy/delete' now takes into account the primary and the
+; motion selection.
+;
+; Revision 2.12  1993/10/08  09:08:46  bosch
+; Avoid highlighting empty lines, even if
+; `mode-motion-highlight-lines-when-behind' is non-nil.
+
+; Revision 2.12  1994/07/07  18:33:38  Russell.Ritchie@gssec.bt.co.uk
+; Made list-motion-handlers and mode-motion-set-handler work in lemacs-19.10.
+; 
+; Revision 2.11  1993/09/20  08:29:15  bosch
+; Code reorganized: variables declared before used.
+; Compatibility hack patched again.
+;
+; Revision 2.10  1993/09/17  18:50:33  bosch
+; Bug in the compatibility hack fixed. Call to `make-cursor' replaced by
+; `x-pointer-cache'. Compatibility hack for Lemacs 19.8 removed.  Tcl
+; motion handler improved (needs still some work).
+;
+; Revision 2.9  1993/09/15  17:52:53  bosch
+; Compatibility patch for Lucid Emacs 19.8. tcl motion handler added.
+;
+; Revision 2.8  1993/08/27  15:17:07  bosch
+; Select window conflict between motion handlers and process filters
+; resolved by using `enqueue-eval-event' for selecting a different
+; window (functions `mode-motion-track-pointer' and
+; `mode-motion-highlight-with-handler' modified). This fixes the nasty
+; bug that made GNUS hanging during NNTP activity while the mouse was
+; moved.
+;
+; Revision 2.7  1993/08/27  12:50:10  bosch
+; TeX and LaTeX motion handler generalized.  Motion handler
+; `highlight-Texinfo' added.
+;
+; Revision 2.6  1993/06/24  11:58:52  bosch
+; Mode motion+ support for pcl-cvs added. #undef syntax for C added.
+;
+; Revision 2.5  1993/06/09  12:04:31  bosch
+; Delivery motion handlers for `c++-c-mode', `gnus-group-mode', and
+; `gnus-summary-mode' added. Mode motion commands bound to copy/cut/past
+; keys for Sun keyboards (f16, f18, f20). Comment added.
+;
+; Revision 2.4  1993/02/15  12:59:47  bosch
+; Modifications sent by Tibor Polgar integrated:
+; Optional parameter added to `mode-motion-copy/delete'.  User option
+; `mode-motion-focus-on-window' added. It controls window selection for
+; the motion handlers. Minor changes of the delivery motion handlers.
+;
+; Revision 2.3  1993/02/04  18:10:09  bosch
+; User option `mode-motion-minibuffer-completion' added. It controls
+; the minibuffer completion highlighting.
+;
+; Revision 2.2  1993/01/27  13:08:12  bosch
+; Improved clearing of `sticky' mode-motion-extents when leaving screen
+; or buffer.  Function `mode-motion-clear-extent' added.
+; Highlight line mouse cursor is behind.
+; `mode-motion-highlight-with-handler' now takes an event as argument.
+; Cut and paste functions renamed and rewritten. Now they are called:
+; `mode-motion-move', `mode-motion-delete', `mode-motion-copy',
+; `mode-motion-copy-as-kill'.  Bug fixes in the C scanner stuff.
+; Motion handler `underline-c' added.
+;
+; Revision 2.1  1993/01/19  18:29:58  bosch
+; Scanner and motion handler for C syntax added.
+; Function `set-default-motion-handler' added.
+; Minor improvements on the `list-motion-handlers' interface done.
+; Minor bug fixes.
+;
+; Revision 2.0 1993/01/14   19:17:29  bosch
+; Lot of things rewritten and reorganized. This version fits in only
+; one file (beside the required package thing.el).
+;
+; New basic features are:
+;  - buffer, mode and default motion handlers
+;  - easy composition of own motion handlers
+;  - listing of motion handlers in tabular form
+;  - menu interface for changing motion handlers
+;  - only two  elisp files: mode-motion+.el, thing.el
+; 
+
+(require 'thing)
+(require 'mode-motion)
+(defconst mode-motion+-version "3.15")
+
+;;; This file defines a set of mouse motion handlers that do some
+;;; highlighting of the text when the mouse moves over.
+;;; An exhaustive list of the motion handlers defined in this file may be
+;;; obtained with M-x list-motion-handlers.
+;;; User Options and their Custommisation
+;;;
+;;; Mode-motion+ provides four user options, defined beyond. See their
+;;; documentation string to know what they are good for. If you want
+;;; to modify their default values, just setq them in your ~/.emacs.
+
+(defvar mode-motion+-religion nil ; Initialised in mode-motion-init.
+  "*Default highlight religion: one of bold, gray, highlight, invert or underline.
+
+Unless you setq this otherwise, it defaults to underline when
+(x-display-color-p) is non-nil and invert otherwise.
+Setting it to 'highlight should cause mode-motion+ extents to be
+indistinguishable from any other type of highlighted extent which may or may
+not be advisable, depending on your point of view.")
+
+(defvar mode-motion-highlight-lines-when-behind t
+  "*If non-nil highlight the whole line if the mouse is past the end.")
+
+(defvar mode-motion-focus-on-window nil
+  "*Controls whether moving the mouse into another window selects this window.
+The following values are possible:
+ 
+nil	  - Window selection isn't influenced at all by mode motion.
+
+t	  - Window selection always follows the mouse cursor. Copying motion
+            active regions doesn't work any longer between different buffers.
+	    
+any other - window selection follows the mouse cursor if the motion handler
+	    of the buffer under the mouse has the follow-point property set.
+	    Useful for selecting line mode buffers just by moving the mouse
+	    inside in order to execute commands there (VM summary,
+	    GNUS Group and Subject, DIRED, Buffer menu etc.)")
+
+(defvar mode-motion-setup-cut-and-paste-bindings t
+  "*If non-nil, bind commands to the Copy, Paste and Cut keys.")
+
+;;  Options sub-menu for mode-motion+
+(defvar mode-motion+-options-menu 
+  '("Motion Highlighting"
+    "For Current Buffer"
+    "---"
+    ["None"
+     (progn
+       (set-buffer-motion-handler (current-buffer) 'no-thing)
+       (mode-motion-clear-extent))
+     :style radio
+     :selected (eq (mode-motion+-buffer-handler-religion (current-buffer))
+		   'no)
+     :active (mode-motion+-active-p)]
+    ["Bold"
+     (progn
+       (modify-buffer-motion-handler (current-buffer) 'bold))
+     :style radio
+     :selected (eq (mode-motion+-buffer-handler-religion (current-buffer))
+		   'bold)
+     :active (mode-motion+-active-p)]
+    ["Underline"
+     (progn
+       (modify-buffer-motion-handler (current-buffer) 'underline))
+     :style radio
+     :selected (eq (mode-motion+-buffer-handler-religion (current-buffer))
+		   'underline)
+     :active (mode-motion+-active-p)]
+    ["Gray"
+     (progn
+       (modify-buffer-motion-handler (current-buffer) 'gray))
+     :style radio
+     :selected (eq (mode-motion+-buffer-handler-religion (current-buffer))
+		   'gray)
+     :active (mode-motion+-active-p)]
+    ["Highlight"
+     (progn
+       (modify-buffer-motion-handler (current-buffer) 'highlight))
+     :style radio
+     :selected (eq (mode-motion+-buffer-handler-religion (current-buffer))
+		   'highlight)
+     :active (mode-motion+-active-p)]
+    ["Invert"
+     (progn
+       (modify-buffer-motion-handler (current-buffer) 'invert))
+     :style radio
+     :selected (eq (mode-motion+-buffer-handler-religion (current-buffer))
+		   'invert)
+     :active (mode-motion+-active-p)]
+    "---"
+    "For Current Mode"
+    "---"
+    ["None"
+     (progn
+       (set-mode-motion-handler major-mode 'no-thing)
+       (mode-motion-clear-extent))
+     :style radio
+     :selected (eq (mode-motion+-mode-handler-religion major-mode) 'no)
+     :active (mode-motion+-active-p)]
+    ["Bold"
+     (progn
+       (modify-mode-motion-handler major-mode 'bold))
+     :style radio
+     :selected (eq (mode-motion+-mode-handler-religion major-mode) 'bold)
+     :active (mode-motion+-active-p)]
+    ["Underline"
+     (progn
+       (modify-mode-motion-handler major-mode 'underline))
+     :style radio
+     :selected (eq (mode-motion+-mode-handler-religion major-mode) 'underline)
+     :active (mode-motion+-active-p)]
+    ["Gray"
+     (progn
+       (modify-mode-motion-handler major-mode 'gray))
+     :style radio
+     :selected (eq (mode-motion+-mode-handler-religion major-mode) 'gray)
+     :active (mode-motion+-active-p)]
+    ["Highlight"
+     (progn
+       (modify-mode-motion-handler major-mode 'highlight))
+     :style radio
+     :selected (eq (mode-motion+-mode-handler-religion major-mode) 'highlight)
+     :active (mode-motion+-active-p)]
+    ["Invert"
+     (progn
+       (modify-mode-motion-handler major-mode 'invert))
+     :style radio
+     :selected (eq (mode-motion+-mode-handler-religion major-mode) 'invert)
+     :active (mode-motion+-active-p)]
+    "---"
+    "For All"
+    "---"
+    ["None"
+     (progn
+       (setq mode-motion+-religion 'no)
+       (mode-motion-init-handlers-according-to-religion 'force)
+       (mode-motion-clear-extent))
+     :style radio
+     :selected (eq mode-motion+-religion 'no)
+     :active (mode-motion+-active-p)]
+    ["Bold"
+     (progn
+       (setq mode-motion+-religion 'bold)
+       (mode-motion-init-handlers-according-to-religion 'force))
+     :style radio
+     :selected (eq mode-motion+-religion 'bold)
+     :active (mode-motion+-active-p)]
+    ["Underline"
+     (progn
+       (setq mode-motion+-religion 'underline)
+       (mode-motion-init-handlers-according-to-religion 'force))
+     :style radio
+     :selected (eq mode-motion+-religion 'underline)
+     :active (mode-motion+-active-p)]
+    ["Gray"
+     (progn
+       (setq mode-motion+-religion 'gray)
+       (mode-motion-init-handlers-according-to-religion 'force))
+     :style radio
+     :selected (eq mode-motion+-religion 'gray)
+     :active (mode-motion+-active-p)]
+    ["Highlight"
+     (progn
+       (setq mode-motion+-religion 'highlight)
+       (mode-motion-init-handlers-according-to-religion 'force))
+     :style radio
+     :selected (eq mode-motion+-religion 'highlight)
+     :active (mode-motion+-active-p)]
+    ["Invert"
+     (progn
+       (setq mode-motion+-religion 'invert)
+       (mode-motion-init-handlers-according-to-religion 'force))
+     :style radio
+     :selected (eq mode-motion+-religion 'invert)
+     :active (mode-motion+-active-p)]
+    "---"
+    ["Minibuffer highlighting" (setq mode-motion-use-minibuffer-motion-handler
+				     (not mode-motion-use-minibuffer-motion-handler))
+     :style toggle :selected mode-motion-use-minibuffer-motion-handler]
+     
+    ["Customize..."
+     (list-motion-handlers)
+     t
+     ;;     nil
+     ]
+     ["Revert Customization"
+     (call-interactively 'mode-motion+-motion-hook-revert)
+     (and (boundp 'mode-motion+-previous-hook) mode-motion+-previous-hook)
+     ])
+  "Menu for changing mode-motion+ religion and other things.")
+
+(defun mode-motion+-active-p ()
+  (cond ((symbolp mode-motion-hook)
+	 (eq mode-motion-hook 'mode-motion+-highlight))
+	((listp mode-motion-hook)
+	 (memq 'mode-motion+-highlight mode-motion-hook))
+	(t nil)))
+     
+(defun mode-motion+-buffer-handler-religion (buffer)
+  (let* ((current-handler-name (symbol-name (motion-handler-name
+					     (get-current-motion-handler))))
+	 (religion-name (substring current-handler-name
+				   0
+				   (string-match "-" current-handler-name))))
+    (intern-soft religion-name)))
+
+(defun mode-motion+-mode-handler-religion (buffer)
+  (let* ((mode-handler (or (get major-mode 'mode-motion-handler)
+			   default-motion-handler))
+	 (current-handler (symbol-name (motion-handler-name mode-handler)))
+	 (religion (substring current-handler
+			      0
+			      (string-match "-" current-handler))))
+    (intern-soft religion)))
+
+(defun modify-buffer-motion-handler (buffer religion)
+  (let* ((current-handler (symbol-name (motion-handler-name
+					     (get-current-motion-handler))))
+	 (suffix (substring current-handler
+			    (string-match "-" current-handler))))
+    (set-buffer-motion-handler buffer
+			       (intern-soft (concat (symbol-name religion)
+						    suffix)))))
+
+(defun modify-mode-motion-handler (mode religion)
+  (let* ((mode-handler (or (get major-mode 'mode-motion-handler)
+			   default-motion-handler))
+	 (current-handler (symbol-name (motion-handler-name mode-handler)))
+	 (suffix (substring current-handler
+			    (string-match "-" current-handler))))
+    (set-mode-motion-handler mode (intern-soft (concat (symbol-name
+							religion)
+						       suffix)))))
+
+;;;; This does not work.  I would like to be able to modify in-place
+;;;; the non-selectable items, but I don't know how.
+;;;; --paquette, Wed Mar  8 23:32:32 1995 (Marc Paquette) 
+;;; Sensitize the mode motion+ options submenu, a la
+;;; sensitize-file-and-edit-menus-hook.
+(defun mode-motion+-sensitize-options-menu-hook ()
+  "Hook function that will adjust title items in the mode-motion+ submenu in Options"
+  (let* ((mm+-menu (cdr (car (find-menu-item
+			      current-menubar
+			      '("Options" "Motion Highlighting")))))
+	 (buffer-item (find-menu-item mm+-menu '("For Current Buffer")))
+	 (mode-item (find-menu-item mm+-menu '("For Current Mode"))))
+    (setcar buffer-item (format "For Buffer `%s'" (buffer-name nil)))
+    (setcar mode-item (format "For Mode `%s'" major-mode))
+    nil))
+
+;;(add-hook 'activate-menubar-hook 'mode-motion+-sensitize-options-menu-hook)
+  
+
+;;  Motion Handler Format:
+;;      
+;; A motion handler is vector with the following format 
+;; [<name> 		       	- a symbol
+;;  <region computing function> - a function or name of function 
+;;				  that returns (<startpos> . <endpos>) 
+;;				  or nil.
+;;  <face or face name>		- as it says ...
+;;  <highlight-p>		- non-nil means that the motion extent
+;;				  will be highlighted using the function 
+;;				  `highlight-extent'
+;;  <follow-point-p>		- non-nil means that point will follow the
+;;				  mouse motion. 
+;; ]
+
+;; accessor functions
+(defsubst motion-handler-name (handler) (aref handler 0))
+(defsubst motion-handler-boundary-function (handler) (aref handler 1))
+(defsubst motion-handler-face (handler) (aref handler 2))
+(defsubst motion-handler-highlight (handler) (aref handler 3))
+(defsubst motion-handler-follow-point (handler) (aref handler 4))
+
+;; modifier functions
+(defsubst set-motion-handler-boundary-function (handler x) (aset handler 1 x))
+(defsubst set-motion-handler-face (handler x) (aset handler 2 x))
+(defsubst set-motion-handler-highlight (handler x) (aset handler 3 x))
+(defsubst set-motion-handler-follow-point (handler x) (aset handler 4 x))
+
+;; Internal global variables 
+(defvar motion-handler-alist ()
+  "Alist with entries of the form \(<name> . <handler>\).")
+
+;; Minibuffer motion handler
+(defvar mode-motion-use-minibuffer-motion-handler t
+  "*Enable mousable highlighting when the minibuffer is active. When false only extents with the
+highlight property are selectable (*Completion*)")
+
+(defvar mode-motion-extent nil)
+(make-variable-buffer-local 'mode-motion-extent)
+(defvar buffer-motion-handler nil)
+(make-variable-buffer-local 'buffer-motion-handler)
+(defvar mode-motion-last-extent nil "The last used mode motion extent.")
+(defvar default-motion-handler nil)	; Initialised in mode-motion-init.
+
+;; Creation of motion handlers
+
+(defun find-motion-handler (name)
+  (or (symbolp name)
+      (setq name (intern-soft name)))
+  (cdr (assq name motion-handler-alist)))
+
+;; internal motion handler creator
+(defsubst make-motion-handler-internal 
+  (name boundary-function face highlight follow-cursor)
+  (vector name boundary-function (get-face face) highlight follow-cursor))
+
+(defun make-motion-handler 
+  (name boundary-function &optional face highlight follow-cursor)
+  "Create a motion handler named NAME (a symbol or string) using REGION-FUNCTION.
+
+REGION-FUNCTION is the function that computes the region to be highlighted. 
+Optional arguments are: 
+
+FACE: A face or face name to be used to highlight the region computed
+      by REGION-FUNCTION.  'default is the default.
+      
+HIGHLIGHT: Flag that indicates whether the highlight attribute of the
+      mode-motion-extent should be set or not. If FACE is the default face, 
+      HIGHLIGHT defaults to t, otherwise to nil.
+
+FOLLOW-CURSOR: Flag that indicates whether the cursor should follow
+      the mouse motion. Default is nil."
+
+  ;; required arguments
+  (or name (error "motion handler name required."))
+  (or (symbolp name) 
+      (stringp name)
+      (error "motion handler name must be a string or symbol: %s" name))
+  (or boundary-function 
+      (error "motion handler region function required."))
+  (or (fboundp boundary-function)
+      (error "not a function: %s." boundary-function))
+  ;; defaults
+  (or face (setq face 'default))
+  
+  ;; store the mode motion handler on the 'mode-motion-handler property of
+  ;; its name symbol
+  (let ((old-handler (cdr (assq name motion-handler-alist)))
+	new-handler)
+    (if old-handler
+	(progn 
+	  (set-motion-handler-boundary-function old-handler boundary-function)
+	  (set-motion-handler-face old-handler (get-face face))
+	  (set-motion-handler-highlight old-handler highlight)
+	  (set-motion-handler-follow-point old-handler follow-cursor))
+      (setq motion-handler-alist 
+	    (cons (cons name 
+			(setq new-handler (make-motion-handler-internal
+					   name
+					   boundary-function
+					   (get-face face)
+					   highlight
+					   follow-cursor)))
+		  motion-handler-alist)))
+    (or old-handler new-handler)))
+
+(defvar list-motion-handlers-buffer-to-customize nil
+  "Name of buffer from where list-motion-handlers was called.")
+(make-variable-buffer-local 'list-motion-handlers-buffer-to-customize)
+(defvar list-motion-handlers-buffer-mode nil
+  "Name of mode of buffer from where list-motion-handlers was called.")
+(make-variable-buffer-local 'list-motion-handlers-buffer-mode)
+;; Listing available motion handlers in tabular form. 
+      
+(defvar basic-motion-handlers (list 'mode-motion-highlight-line
+				    'mode-motion-highlight-word
+				    'mode-motion-highlight-symbol
+				    'mode-motion-highlight-sexp)
+  "The basic motion handlers provided by the underlying XEmacs.")
+
+(defun list-motion-handlers ()
+  "Display a list of available motion handlers.
+The listing is in tabular form and contains the following columns:
+NAME: the motion handlers name,
+BOUNDARY FUNCTION: the name of the funtion used to compute the text  
+   highlighted by the motion handler,
+FACE: the face used to highlight the text.
+
+Additionally, the following flags are used at the beginning of each line:
+`*' Marks the motion handler current to the buffer this functions was called 
+    from.
+`H' Force highlighting of the selected text.
+`F' Make point follow the mouse cursor as it moves."
+  (interactive)
+  (let ((current-handler (get-current-motion-handler))
+	(buffer (current-buffer))
+	(buffer-mode major-mode)
+	(bmmh (if (symbolp mode-motion-hook)
+		  (car (memq mode-motion-hook basic-motion-handlers))
+		(if (and (listp mode-motion-hook) 
+			 (equal 1 (length mode-motion-hook)))
+		    (car (memq (car mode-motion-hook)
+			       basic-motion-handlers))))))
+    (save-excursion
+      (with-output-to-temp-buffer "*Mouse Motion Handlers*"
+	(let ((truncate-lines t))
+	  (set-buffer "*Mouse Motion Handlers*")
+	  (setq list-motion-handlers-buffer-to-customize buffer)
+	  (setq list-motion-handlers-buffer-mode buffer-mode)
+	  (let ((pos1 5)
+		(pos2 25)
+		(pos3 50)
+		(handlers 
+		 (sort 
+		  (mapcar 'cdr motion-handler-alist)
+		  '(lambda (x y)
+		     (string<
+		      (symbol-name (motion-handler-boundary-function x))
+		      (symbol-name (motion-handler-boundary-function y)))))))
+	    (if bmmh
+		(let ((i 1)
+		      (fw (frame-width)))
+		  (while (< i fw)
+		    (princ "*")
+		    (setq i (1+ i)))
+		  (princ "\nNote: this buffer is not using mode-motion+.\n\n")
+		  (princ "It's using the `")
+		  (princ bmmh)
+		  (princ "' motion handler which claims it's:\n")
+		  (insert (documentation bmmh))
+		  (princ "\nSetting this motion handler will be irrevocable from this interface\n(but only for duration of this XEmacs session).\n")
+		  (setq i 1)
+		  (while (< i fw)
+		    (princ "*")
+		    (setq i (1+ i)))
+		  (terpri)))
+	    (princ "     NAME                BOUNDARY FUNCTION        FACE\n")
+	    (princ "     ----                -----------------        ----\n")
+	    (mapcar 
+	     #'(lambda (handler)
+		 (let ((line-start (point)))
+		   (princ (if (and (not bmmh) (eq handler current-handler))
+			      "*" " "))
+		   (princ (if (eq handler default-motion-handler) "D" " "))
+		   (princ (if (motion-handler-highlight handler) "H" " "))
+		   (princ (if (motion-handler-follow-point handler) "F" " "))
+		   (indent-to-column pos1 1)
+		   (princ (motion-handler-name handler))
+		   (indent-to-column pos2 1)
+		   (princ (motion-handler-boundary-function handler))
+		   (indent-to-column pos3)
+		   (let ((face-start (point)))
+		     (princ (face-name (motion-handler-face handler)))
+		     (let ((line-extent (make-extent line-start face-start))
+			   (face-extent (make-extent face-start (point))))
+		     (set-extent-face face-extent
+				      (motion-handler-face handler))
+		     (set-extent-property
+		      face-extent
+		      'mode-motion-handler (motion-handler-name handler))
+		     (set-extent-property
+		      line-extent
+		      'mode-motion-handler (motion-handler-name handler))
+		     (set-extent-property line-extent 'highlight t)))
+		 (terpri)))
+	     handlers)
+	    (princ (format "
+Flags:	`D' the default motion handler
+       	`H' handler with highlighting
+	`F' handler with `following' property
+	`*' the motion handler of buffer \"%s\""
+			   list-motion-handlers-buffer-to-customize))))
+	(local-set-key 'button3 'mode-motion-set-handler)
+	(setq buffer-read-only t)))))
+
+(defun mode-motion-set-handler (event)
+  (interactive "@e")
+  (let* ((handler (or (extent-property
+		       (extent-at (event-point event) (current-buffer)
+				  'mode-motion-handler)
+		       'mode-motion-handler)
+		      (error "Click on highlighted line to select a handler")))
+	 (menu (list
+		(format "Make `%s' the Motion Handler of :" handler)
+		(vector (format "Buffer %s"
+				list-motion-handlers-buffer-to-customize)
+			(` (set-buffer-motion-handler
+			    '(, list-motion-handlers-buffer-to-customize)
+			    '(, handler))) t)
+		(vector "Another Buffer..."
+			(` (motion-handler-list-set-buffer-handler
+			    '(, handler))) t)
+		"---"
+		(vector (format "Mode %s"
+				list-motion-handlers-buffer-mode)
+			(` (progn
+			     (set-mode-motion-handler
+			      '(, list-motion-handlers-buffer-mode)
+			      '(, handler))
+			     (save-excursion
+			       (mapcar
+				(function
+				 (lambda (buf)
+				   (set-buffer buf)
+				   (and (eq
+					 '(, list-motion-handlers-buffer-mode)
+					 major-mode)
+					(mode-motion+-hook-install buf t))))
+				       (buffer-list))))) t)
+		(vector "Another Mode..."
+			(` (motion-handler-list-set-mode-handler
+			    '(, handler))) t)
+		"---"
+		(vector "Default Motion Handler"
+			(` (set-default-motion-handler '(, handler))) t))))
+    (popup-menu menu)))
+
+(defun motion-handler-list-set-buffer-handler (handler)
+  (let ((buffer (read-buffer-name 
+		 (format "Make `%s' the motion handler of buffer: " handler)
+		 (buffer-name list-motion-handlers-buffer-to-customize))))
+    (set-buffer-motion-handler buffer handler)
+    (save-excursion
+      (set-buffer buffer)
+      (and (not (cond ((listp mode-motion-hook)
+		       (memq 'mode-motion+-highlight mode-motion-hook))
+		      ((symbolp mode-motion-hook)
+		       (eq 'mode-motion+-highlight mode-motion-hook))
+		      (t t)))
+	   (y-or-n-p (format "Augment the default mode motion hook for `%s'? "
+			     (buffer-name nil)))
+	   (mode-motion+-hook-install buffer t)))))
+
+(defvar mode-motion+-previous-hook nil
+  "Value of previous `mode-motion-hook' in current buffer.")
+(make-variable-buffer-local 'mode-motion+-previous-hook)
+
+(defun motion-handler-list-set-mode-handler (handler)
+  (let ((mode (intern (completing-read
+	    (format "Make `%s' the motion handler of mode: " handler)
+	    obarray
+	    'fboundp
+	    t	
+	    (symbol-name list-motion-handlers-buffer-mode)))))
+    (set-mode-motion-handler mode handler)
+  (save-excursion
+    (mapcar (function
+	     (lambda (buf)
+	       (set-buffer buf)
+	       (and (eq mode major-mode)
+		    (mode-motion+-hook-install buf t))))
+	    (buffer-list)))))
+
+(defun mode-motion+-hook-install (&optional buffer remove-highlight-line-p)
+  "Add `mode-motion+-highlight' to the BUFFER `mode-motion-hook'.
+If the optional second arg REMOVE-HIGHLIGHT-LINE-P is t, remove
+`mode-motion-highlight-line' from `mode-motion-hook'.
+See `mode-motion+-hook-uninstall' for reverting this operation."
+  (interactive "bInstall mode-motion+ hook for buffer :
+XRemove highlight-line from hook ? :")
+  ;; Check for the mode-motion-hook value to make sure it's under
+  ;; the control of mode-motion+.
+  ;; The reasonning here is that if the user went trough the hassles
+  ;; of list-motion-handlers (or if he's calling this directly from
+  ;; his .emacs) , he is prepared to give up on the current
+  ;; mode-motion-hook.
+  ;; However, we keep the previous hook value in a buffer-local
+  ;; variable: it will be then possible to revert to the old motion
+  ;; handling behavior with `mode-motion+-hook-uninstall'.
+  ;; --paquette, Mon Feb 27 08:54:30 1995 (Marc Paquette)
+  (setq buffer (or buffer (current-buffer)))
+  ;; force the uninstall of mode-motion-highlight since if its second
+  ;; you'll never see ours.
+  (setq remove-highlight-line-p t)
+  (save-excursion
+    (set-buffer buffer)
+    (if (boundp 'mode-motion-hook)
+	(progn
+	  (setq mode-motion+-previous-hook
+		(cond ((sequencep mode-motion-hook)
+		       (copy-sequence mode-motion-hook))
+		      (t mode-motion-hook)))
+	  ;; Make sure that the mode-motion+-highlight is not saved in
+	  ;; the variable, otherwise, we could not revert back to the
+	  ;; "factory settings" after having played with different
+	  ;; handlers
+	  ;; --paquette, Mon Feb 27 08:54:21 1995 (Marc Paquette)
+	  (remove-hook 'mode-motion+-previous-hook 'mode-motion+-highlight)))
+    (add-hook 'mode-motion-hook 'mode-motion+-highlight)
+    (and remove-highlight-line-p
+	 ;; Remove the standard mode-motion-highlight hook because we
+	 ;; provide an alternative to this.  I don't use setq here because
+	 ;; something else could be hooked to mode-motion-hook.
+	 ;; --paquette, Mon Feb 27 08:53:51 1995 (Marc Paquette)
+	 (remove-hook 'mode-motion-hook 'mode-motion-highlight-line))
+    (and mode-motion-extent
+	 (delete-extent mode-motion-extent)
+	 (setq mode-motion-extent nil))
+    ;; Try to make this installed for any buffer of this mode
+    (let ((this-mode-hook (intern-soft (concat (symbol-name major-mode)
+					       "-hook"))))
+      (and (boundp this-mode-hook)
+	   (if remove-highlight-line-p
+	       (add-hook this-mode-hook
+			 #'(lambda () (mode-motion+-hook-install nil t))
+			 'append)
+	     (add-hook this-mode-hook 'mode-motion+-hook-install 'append)))))
+  mode-motion-hook)
+
+(defun mode-motion+-hook-uninstall (buffer)
+  "Restore the value of `mode-motion-hook' in BUFFER to what it was at the time `mode-motion+-hook-install' was called.
+See also `mode-motion+-hook-install'."
+  (interactive "bRestore `mode-motion-hook' of buffer :")
+  ;; Check for the mode-motion-hook value to make sure it's under
+  ;; the control of mode-motion+.
+  ;; The reasonning here is that if the user went trough the hassles
+  ;; of list-motion-handlers (or if he's calling this directly from
+  ;; his .emacs) , he is prepared to give up on the current
+  ;; mode-motion-hook.
+  ;; However, we keep the previous hook value in a buffer-local
+  ;; variable: it will be then possible to revert to the old motion
+  ;; handling behavior with `mode-motion+-hook-uninstall'.
+  ;; --paquette, Mon Feb 27 08:54:30 1995 (Marc Paquette)
+  (save-excursion
+    (set-buffer buffer)
+    (and mode-motion-extent
+	 (delete-extent mode-motion-extent)
+	 (setq mode-motion-extent nil))
+    (if (boundp 'mode-motion+-previous-hook)
+	(progn
+	  (setq mode-motion-hook mode-motion+-previous-hook)
+	  (setq mode-motion+-previous-hook nil)
+	  (let ((this-mode-hook (intern-soft (concat (symbol-name major-mode)
+						     "-hook"))))
+	    (and (boundp this-mode-hook)
+		 (remove-hook this-mode-hook 'mode-motion+-hook-install))))
+      (error "No previous value for mode-motion-hook")))
+  mode-motion-hook)
+
+(defun mode-motion+-motion-hook-revert (&optional buffer-only-p buffer mode)
+  "Revert the `mode-motion-hook' to its original value.
+With optional arg BUFFER-ONLY-P non-nil, only revert in BUFFER
+\(defaults to `\(current-buffer\)'\); otherwise, revert for all existing
+buffers of MODE \(defaults to `major-mode' of BUFFER\)."
+  (interactive
+    (let* ((buffer-only-p
+	   (y-or-n-p "Revert mode-motion-hook only for current buffer ? "))
+	   (buffer (if buffer-only-p
+		       (current-buffer)
+		     (get-buffer (read-buffer-name
+				  "Revert mode-motion-hook of buffer : "
+				  (buffer-name (current-buffer))))))
+	   (mode (if buffer-only-p
+		     (save-excursion
+		       (set-buffer buffer)
+		       major-mode)
+		   (intern-soft (completing-read "Major mode: "
+						 obarray
+						 'fboundp	
+						 nil 
+						 (symbol-name major-mode))))))
+      (list buffer-only-p buffer mode)))
+  (if buffer-only-p
+      (mode-motion+-hook-uninstall buffer)
+    (save-excursion
+      (mapcar (function
+	       (lambda (buf)
+		 (set-buffer buf)
+		 (and (eq mode major-mode)
+		      (mode-motion+-hook-uninstall buf))))
+	      (buffer-list)))))
+  
+
+;; Setting buffer, mode and default motion handlers
+
+(defun set-buffer-motion-handler (buffer handler-name)
+  "Make the motion handler named HANDLER-NAME (a symbol) the buffer
+motion handler of BUFFER.  If HANDLER-NAME is nil, the corresponding
+buffer motion handler is removed.  If HANDLER-NAME isn't the name of a
+known motion handler, an error is signaled. When called interactively,
+completion is provided for available buffers and motion handlers.
+
+	1.\) buffer motion handler
+	2.\) mode motion handler
+	3.\) default motion handler"
+  (interactive (list (read-buffer-name "Set motion handler of buffer: "
+				       (buffer-name (current-buffer)))
+		     (read-motion-handler-name)))
+
+  ;; kill old mode motion extent, because the new handler
+  ;; might want to initialize it differently
+  (if mode-motion-extent 
+      (progn 
+	(detach-extent mode-motion-extent)
+	(setq mode-motion-extent nil)))
+  (or buffer (setq buffer (current-buffer)))
+  (or (get-buffer buffer)
+      (error "No such buffer: %s" buffer))
+  (save-excursion 
+    (set-buffer buffer)
+    (setq buffer-motion-handler
+	  ;; remove it if `nil'
+	  (and handler-name
+	       ;; set the handler if known
+	       (or (find-motion-handler handler-name)
+		   ;; error otherwise
+		   (error "Not a known motion handler: %s"
+			  handler-name)))))
+  (if (interactive-p)
+      (if handler-name
+	  (message "Motion handler for buffer %s is `%s'." 
+		   (current-buffer) handler-name)
+	  (message "Motion handler removed for buffer %s." 
+		   (current-buffer))))
+  handler-name)
+
+(defun read-buffer-name (prompt &optional initial-input)
+  (completing-read prompt
+		   (mapcar #'(lambda (buf) (list (buffer-name buf)))
+			   (buffer-list))
+		   ;; don't take buffers that start with a blank
+		   #'(lambda (list) (not (eq (aref (car list) 0) ? )))
+		   t
+		   initial-input))
+
+(defun set-mode-motion-handler (mode handler-name)
+  "Make the motion handler named HANDLER-NAME (a symbol) the mode motion
+handler for all buffers with major-mode MODE.  If HANDLER-NAME is nil,
+the corresponding mode motion handler is removed.  If HANDLER-NAME
+isn't the name of a known motion handler, an error is signaled. When
+called interactively, completion is provided for available motion
+handlers.
+
+	1.\) buffer motion handler
+	2.\) mode motion handler
+	3.\) default motion handler"
+  (interactive (list (intern (completing-read "Major mode: "
+					      obarray
+					      'fboundp	
+					      nil 
+					      (symbol-name major-mode)))
+		     (read-motion-handler-name)))
+  ;; kill old mode motion extent, because the new handler
+  ;; might want to initialize it differently
+  (if mode-motion-extent 
+      (progn 
+	(detach-extent mode-motion-extent)
+	(setq mode-motion-extent nil)))
+  (put mode 'mode-motion-handler 
+	;; remove it if `nil'
+	(and handler-name
+	     ;; set the handler if known
+	     (or (find-motion-handler handler-name)
+		 ;; error otherwise
+		 (error "Not a known mode motion handler: %s" handler-name))))
+  (if (interactive-p)
+      (if handler-name
+	  (message "Motion handler for %s is `%s'." mode handler-name)
+	  (message "Mode motion handler for %s removed." mode)))
+  handler-name)
+
+(defun set-default-motion-handler (handler-name)
+  "Make the motion handler named HANDLER-NAME (a symbol) the default.
+
+If HANDLER-NAME is nil, the current default motion handler is removed.  If
+HANDLER-NAME isn't the name of a known motion handler, an error is
+signalled. When called interactively, completion is provided for available
+motion handlers.
+
+The motion handler used in a given buffer is determined by the following
+most-specific first list: buffer motion handler, mode motion handler, default
+motion handler." 
+  (interactive (list (read-motion-handler-name)))
+  ;; kill old mode motion extent, because the new handler
+  ;; might want to initialize it differently
+  (if mode-motion-extent 
+      (progn 
+	(detach-extent mode-motion-extent)
+	(setq mode-motion-extent nil)))
+  (setq default-motion-handler
+	;; remove it if `nil'
+	(and handler-name
+	     ;; set the handler if known
+	     (or (find-motion-handler handler-name)
+		 ;; error otherwise
+		 (error "Not a known motion handler: %s" handler-name))))
+  (if (interactive-p)
+      (if handler-name
+	  (message "Default motion handler is `%s'." handler-name)
+	  (message "Default motion handler removed.")))
+  handler-name)
+
+(defun read-motion-handler-name ()
+  (intern-soft (completing-read "Motion handler: "
+				(mapcar #'(lambda (entry)
+					    (list (symbol-name (car entry))))
+					motion-handler-alist)
+				nil t)))
+
+;; clear the last active motion extent when leaving a frame.
+(defun mode-motion-clear-extent (&optional extent)
+  "Clear EXTENT, i.e. make it have no visible effects on the frame.
+EXTENT defaults to the current buffer's mode-motion-extent."
+  (or extent (setq extent mode-motion-extent))
+  (and extent 
+       (extent-live-p extent)
+       (not (extent-detached-p extent))
+       (extent-buffer extent)
+       (buffer-name (extent-buffer extent))
+       (progn 
+	 ;; unhighlight it 
+	 (highlight-extent extent nil)
+	 ;; make it span a region that isn't visible and selectable
+	 ;; Can this be done more elegantly? 
+	 (detach-extent extent))))
+
+(defun mode-motion-clear-last-extent (&optional frame)
+  "Clear the mode-motion-last-extent."
+  (or (popup-menu-up-p) (mode-motion-clear-extent mode-motion-last-extent)))
+
+(defun mode-motion+-highlight (event)
+  "Highlight the thing under the mouse using a mode-specfic motion handler.
+See list-motion-handlers for more details."
+  (mode-motion-clear-last-extent)
+  (and (event-buffer event)
+       (cond ((and mouse-grabbed-buffer
+		   ;; first try to do minibuffer specific highlighting
+		   (find-motion-handler 'minibuffer)
+		   (let ((mode-motion-highlight-lines-when-behind nil))
+		     (and (event-point event)
+			  (or (extent-at (event-point event)
+					 (event-buffer event) 'highlight)
+			      (mode-motion-highlight-with-handler
+			       (find-motion-handler 'minibuffer) event))))))
+	     (t (mode-motion-highlight-with-handler
+		 (get-current-motion-handler) event))))
+  ;; Return nil since now this is used as a hook, and we want to let
+  ;; any other hook run after us.
+  nil)
+
+(defun get-current-motion-handler ()
+  (or (and (boundp 'buffer-motion-handler) buffer-motion-handler)
+      (get major-mode 'mode-motion-handler)
+      default-motion-handler))
+
+(defun mode-motion-highlight-with-handler (handler event)
+  ;; Perform motion highlighting using HANDLER. Information about the
+  ;; current mouse position is taken form EVENT. 
+  (and handler
+       (let ((point (event-point event))
+	     (buffer (event-buffer event))
+	     (window (event-window event))
+	     (window-config (current-window-configuration))
+	     (buffer-save (current-buffer))
+	     (point-save (point))
+	     region)
+	 ;; save-window-excursion and restore buffer
+	 (unwind-protect
+	     (progn
+	       (and buffer
+		    (set-buffer buffer)
+		    (select-window window))
+	   
+	       ;; kludge: if point = end-of-window, then probably the mouse
+	       ;; is actually between the last line and the modeline.  In
+	       ;; this case move point to back one
+	       (and point
+		    (not (< point (window-end window)))
+		    (setq point (1- point)))
+	       ;; Create a new mode-motion-extent if there isn't one 
+	       ;; (or a destroyed one)
+	       (if (and (extent-live-p mode-motion-extent)
+			(extent-buffer mode-motion-extent))
+		   ()
+		 (setq mode-motion-extent (make-extent nil nil buffer))
+		 (set-extent-priority mode-motion-extent 1))
+	       (if (and 
+		    ;; compute the region to be highlighted
+		    (setq region
+			  (if point
+			      ;; compute the mode-motion region using the 
+			      ;; handlers boundary function
+			      (condition-case nil;; c
+				  (funcall
+				   (motion-handler-boundary-function handler)
+				   point)
+				;; Messages that appear during computing the
+				;; region may be displayed not done
+				;; here because it's rather disturbing
+				(error
+				 ;; (setq message (format "%s" (car (cdr c))))
+				 nil))
+			    ;; otherwise highlight the whole line mouse is
+			    ;; behind but only if the line isn't empty
+			    (if mode-motion-highlight-lines-when-behind
+				(unwind-protect
+				    (progn 
+				      ;; (message "%s" (event-window event))
+				      (move-to-window-line
+				       (if (< emacs-minor-version 12)
+					   (- (event-y event) 
+					      (nth 1 (window-edges window)))
+					 (event-y event)))
+				      (beginning-of-line)
+				      (if (= (following-char) ?\n)
+					  ;; empty line 
+					  ()
+					(thing-region
+					 (point)
+					 (progn 
+					   (end-of-line)
+					   ;; for `follow-point' behavoir
+					   (setq point (point))
+					   ;; fetch also the newline, if any
+					   ;; -- handy for copying >1 line
+					   (if (eobp) point (1+ point))))))
+				  (goto-char point-save)))))
+		    ;; (message "region: %s" region)
+		    ;; the region might be in reverse order. Stop in this case
+		    (<= (car region) (cdr region)))
+		   (if (or (not (motion-handler-follow-point handler))
+			   (pos-visible-in-window-p point))
+		       (progn
+			 ;; set the extent face
+			 (set-extent-face
+			  mode-motion-extent (motion-handler-face handler))
+			 ;; set the new boundary
+			 (set-extent-endpoints 
+			  mode-motion-extent (car region) (cdr region))
+			 ;; highlight if required
+			 (set-extent-property
+			  mode-motion-extent 'highlight
+			  (motion-handler-highlight handler))
+			 (highlight-extent mode-motion-extent
+					   (motion-handler-highlight handler))
+			 ;; make point follow the mouse or point to
+			 ;; the beginning of the line do not move the
+			 ;; cursor if a mark is set.
+			 (cond ((and (motion-handler-follow-point handler)
+				     (not (mark)))
+				(goto-char point)
+				;; kludge to keep the cursor out the way
+				(if (or (eq (motion-handler-boundary-function
+					     handler)
+					    'line-boundaries)
+					(eq (motion-handler-boundary-function
+					     handler)
+					    'visible-line-boundaries))
+				    (beginning-of-line))))
+			 (if (and mode-motion-focus-on-window
+				  (or (eq mode-motion-focus-on-window t)
+				      (motion-handler-follow-point handler)))
+			     ;; Select the current window FROM OUTSIDE the
+			     ;; `save-window-excursion' that surrounds the call
+			     ;; to the current function. This also avoids
+			     ;; conflicts with running process filters.
+			     (enqueue-eval-event 'select-window
+						 (selected-window)))
+			 ;; snap in effect, but it ain't yet workin'
+			 ;; (message "X: %sl; Y: %s"(event-x event)(event-y event))
+			 ;; (and motion-handler-snap-in
+			 ;;    (set-mouse-position
+			 ;;    (window-frame (event-window event))
+			 ;;    (event-x event)
+			 ;;    (event-y event)))
+			 (setq mode-motion-last-extent mode-motion-extent)
+			 ;; signal success
+			 t))
+		 ;; signal failiure
+		 nil))
+	   (set-window-configuration window-config)
+	   (set-buffer buffer-save)))))
+
+;; Motion Event debugging
+;;
+;; Useful to see what information is available from motion events
+
+(defun debug-motion-handler (event)
+   (let* ((window (event-window event))
+	  (frame (or (event-frame event) (selected-frame)))
+	  (buffer (and window (event-buffer event)))
+	  (point  (and buffer (event-point event))))
+     (with-output-to-temp-buffer "*Debug Motion Handler Output*"
+       (princ 
+	(format "\
+ Window: %s
+ Frame: %s
+ Buffer: %s
+ (event-x, event-y): (%s, %s)
+ (event-x-pixel, event-y-pixel): (%s, %s)
+ Point: %s
+ Timestamp: %s"
+	window 
+        frame 
+        buffer 
+        (event-x event) (event-y event) 
+        (event-x-pixel event) (event-y-pixel event)
+        point 
+        (event-timestamp event))))))
+
+;(let ((mouse-motion-handler 'debug-motion-handler)
+;      (temp-buffer-show-function nil))
+;  (read-char))
+
+;; Set of copy/kill/move functions for usage with highlighted regions
+
+(put 'mode-motion-move 'pending-delete t)
+(put 'mode-motion-copy 'pending-delete t)
+
+(defun mode-motion-move ()
+  "Move the motion active region to point." 
+  (interactive)
+  (mode-motion-insert-text (mode-motion-copy/delete t)))
+
+(defun mode-motion-kill ()
+  "Kill the motion active region and push it onto the kill ring."
+  (interactive)
+  (mode-motion-copy/delete t t t))
+
+(defun mode-motion-copy ()
+  "Copy the motion active region to point."
+  (interactive)
+  (mode-motion-insert-text (mode-motion-copy/delete)))
+
+(defun mode-motion-copy-as-kill ()
+  "Delete the motion active region and push it onto the kill ring.
+Set point to the place where deletion happened."
+  (interactive)
+  (mode-motion-copy/delete nil t)
+  (message "Text copied to the to ring and cut buffer."))
+
+(defun mode-motion-copy/delete (&optional delete copy-as-kill set-point)
+  "Return the string that is designated by the current motion active region. 
+Arguments are:
+           EVENT - a mouse click event used to identify the buffer and window 
+&optional DELETE - delete the motion active text region
+    COPY-AS-KILL - copy the string to the kill ring
+       SET-POINT - set point to the start of the motion active region."
+  (let ((old-buf (current-buffer))
+	(old-window (selected-window)))
+    (unwind-protect 
+	(let ((extent (or primary-selection-extent
+			  (and (extentp mode-motion-last-extent)
+			       (not (extent-property mode-motion-last-extent
+						     'detached))
+			       mode-motion-last-extent))))
+
+	  (if (and (extentp extent)
+		   (set-buffer (extent-buffer extent))
+		   (not 
+		    ;; zero length extents
+		    (= (extent-start-position extent)
+		       (extent-end-position extent))))
+
+	      (let* ((start (extent-start-position extent))
+		     (end (extent-end-position extent))
+		     (text 
+		      (buffer-substring
+		       (extent-start-position extent)
+		       (extent-end-position extent))))
+
+		(cond (copy-as-kill
+		       (copy-region-as-kill start end)
+		       (if (or (not kill-hooks)
+				(eq kill-hooks 'ignore))
+			   (progn 
+			     (x-own-selection-internal 'PRIMARY text)
+			     (x-own-clipboard text)))))
+
+		(cond (delete 
+		       (kill-region start end)
+		       (x-own-selection-internal 'PRIMARY text)
+		       ;; (select-window window)
+		       (if set-point 
+			   (goto-char start))))
+
+		(setq this-command 'mode-motion+)
+		text)
+	    (error "No current primary or motion selection.")
+	    ))
+      (set-buffer old-buf)
+      (select-window old-window))))
+
+(defun mode-motion-insert-text (text)
+  "Insert TEXT at point. Also insert one space if the 
+preceeding character is a word constituent or a closing paren."
+  (or text (error "No highlighted text to copy."))
+  (let ((prec-char-syntax (char-syntax (preceding-char))))
+    (if (memq  prec-char-syntax '(?w ?\))) (insert " "))
+    (insert text)))
+
+;; Boundary functions
+;;
+;; The following  functions are already provided by the thing package:
+;; thing-boundaries
+;; thing-symbol
+;; thing-word
+
+(defun char-boundaries (point) (thing-region point (1+ point)))
+      
+(defun visible-line-boundaries (point)
+  (save-excursion
+    (goto-char point)
+    (beginning-of-line)
+    (skip-chars-forward " \t")
+    (if (and (eq major-mode 'dired-mode)
+	     (save-excursion (dired-move-to-filename)))
+	(let ((start (point)))
+	  (end-of-line)
+	  (skip-chars-backward " \t")
+	  (thing-region start (point))))))
+
+(defun line-boundaries (point)
+  (save-excursion
+    (goto-char point)
+    (beginning-of-line)
+    (if (and (eq major-mode 'dired-mode)
+	     (save-excursion (dired-move-to-filename)))
+	(let ((start (point)))
+	  (end-of-line)
+	  (thing-region start (point))))))
+
+(defun cvs-line-boundaries (point)
+    (save-excursion
+      (goto-char point)
+      (beginning-of-line)
+      (if (looking-at "^[* ] ")
+	  (thing-region  (point) (progn (end-of-line) (point))))))
+      
+(defun latex-boundaries (here)
+  (setq *last-thing* 'sexp)
+  (tex-boundaries 
+   here ?\\ "a-zA-Z"
+   ;; begin-fwd-regexp
+   "\\\\begin *{ *\\([a-z]*\\) *}"
+   ;; end-fwd-regexp
+   "\\(\\\\end *{ *%s *}\\)\\|\\(\\\\begin *{ *%s *}\\)"
+   ;; begin-bwd-regexp
+   "\\\\end *{ *\\([a-z]*\\) *}"
+   ;; begin-bwd-regexp
+   "\\(\\\\end *{ *%s *}\\)\\|\\(\\\\begin *{ *%s *}\\)"
+   ;; param-cmd-regexp
+   "\\\\[a-zA-Z]+[ \n\t]*{"))
+
+(defvar texinfo-paired-commands 
+  (mapconcat 
+   'identity 
+   '(
+     "enumerate"
+     "example"
+     "group"
+     "ifinfo" 
+     "iftex" 
+     "ignore" 
+     "itemize"
+     "menu"
+     "quotation"
+     "table"
+     "tex"
+     "titlepage"
+     ) 
+   "\\|"))
+
+(defvar texinfo-begin-fwd-regexp 
+  (format "@\\(%s\\)" texinfo-paired-commands))
+(defvar texinfo-end-bwd-regexp
+  (format "@end *\\(%s\\)" texinfo-paired-commands))
+
+(defun texinfo-boundaries (here)
+  (tex-boundaries 
+   here ?@ "a-z"
+   texinfo-begin-fwd-regexp
+   ;; end-fwd-regexp
+   "\\(@end *%s\\)\\|\\(@%s\\)"
+   ;; end-bwd-regexp
+   texinfo-end-bwd-regexp
+   ;; begin-bwd-regexp
+   "\\(@end *%s\\)\\|\\(@%s\\)"
+   ;; param-cmd-regexp
+   "@\\(TeX\\|[a-zA]+\\)[ \n\t]*{"))
+
+(defun tex-boundaries 
+  (here cmd-start-character cmd-word-character
+	begin-fwd-regexp end-fwd-regexp
+	end-bwd-regexp begin-bwd-regexp
+	param-cmd-regexp)
+  "Generic TeX dialect scanner.
+Parameters: 
+cmd-start-character: character that starts a command 
+	(`\' in (La)TeX, `@' in Texinfo)
+cmd-word-character:  regexpression to be used by the function
+	`skip-chars-backward' allowing to skip over command 
+	characters other than `cmd-start-character'
+begin-fwd-regexp: regexpression matching the begin part of a 
+	text stretch, used in forward search. 
+end-fwd-regexp: regexpression matching the end part of a 
+	text stretch, used in forward search
+end-bwd-regexp: regexpression matching the end part of a 
+	text stretch, used in backward search.
+begin-bwd-regexp: regexpression matching the begin part of a 
+	text stretch, used in backward search.
+param-cmd-regexp: regexpression matching a parameterized command 
+        \(including the open parenthesis\)"
+  (save-excursion
+    (goto-char here)
+    (cond ((= (following-char) cmd-start-character)
+	   (forward-char 1))
+	  ((= (char-syntax (following-char)) ?w)
+	   (skip-chars-backward cmd-word-character)))
+    (if (/= (preceding-char) cmd-start-character)
+	(thing-boundaries here)
+      (forward-char -1)
+      (catch 'return 
+	(cond ((looking-at begin-fwd-regexp)
+	       (let* ((start (point))
+		      (env (buffer-substring 
+			    (match-beginning 1) (match-end 1)))
+		      (regexp (format end-fwd-regexp env env))
+		      (count 0))
+		 (while (re-search-forward regexp nil t)
+		   (cond ((match-beginning 2) ; \begin
+			  (setq count (1+ count)))
+			 ((match-beginning 1) ; \end
+			  (setq count (1- count))
+			  (if (= count 0) 
+			      (throw 'return 
+				     (thing-region start (point)))))))))
+	      ((looking-at end-bwd-regexp)
+	       (let* ((end (match-end 0))
+		      (env (buffer-substring 
+			    (match-beginning 1) (match-end 1)))
+		      (regexp 
+		       (format begin-bwd-regexp env env))
+		      (count 1))
+		 (while (re-search-backward regexp nil t)
+		   (cond ((match-beginning 1) ; \end
+			  (setq count (1+ count)))
+			 ((match-beginning 2) ; \begin
+			  (setq count (1- count))
+			  (if (= count 0) 
+			      (throw 'return (thing-region (point) end))))
+			 ))))
+	      ;; tex macros of the form \cmd {...}
+	      ((looking-at param-cmd-regexp)
+	       (thing-region 
+		(point)
+		(progn 
+		  (goto-char (1- (match-end 0)))
+		  (forward-sexp 1)
+		  (point))))
+	      ;; fetch the current macro (with backslash)
+	      (t (thing-region (point) (progn (forward-word 1) (point)))))))))
+
+;; special parse of buffer for valid selectable info
+(defun minibuffer-selection-boundaries (point)
+  (let ((old-syntax (syntax-table)))
+    (unwind-protect
+	(progn 
+	  ;; best syntax table for recognizing symbols
+	  (set-syntax-table emacs-lisp-mode-syntax-table)
+	  (let ((file-completion (eq minibuffer-completion-table
+				     'read-file-name-internal))
+		region
+		minibuf-string		;contents of minibuffer
+		buffer-string		;string to be highlighted (or not)
+		prefix			;prefix calculated from minibuf-string
+		string			;string to be verified in the
+					;completion table 
+		)
+	    (and
+
+	     (setq region (if file-completion
+			      (thing-filename point)
+			    (thing-symbol point)))
+
+	     (setq
+	      minibuf-string		; contents of minibuffer
+	      (save-excursion
+		(set-buffer mouse-grabbed-buffer)
+		(buffer-string))
+
+	      buffer-string		; string to be highlighted (or not)
+	      (buffer-substring (car region) (cdr region))
+		       
+	      prefix
+	      (if file-completion
+		  (file-name-nondirectory minibuf-string)
+		minibuf-string)
+
+	      string
+	      (if file-completion
+		  (concat (file-name-directory minibuf-string) buffer-string)
+		buffer-string))
+	     
+	     (if (or (and (fboundp 'ange-ftp-ftp-path)
+			  (or (ange-ftp-ftp-path buffer-string)
+			      (ange-ftp-ftp-path string)))
+		     (and (fboundp 'efs-ftp-path)
+			  (or (efs-ftp-path buffer-string)
+			      (efs-ftp-path string))))
+		 ;; #### Like our counterpart in mode-motion: evil evil evil
+		 t
+	       (if file-completion
+		   (try-completion string
+				   minibuffer-completion-table
+				   minibuffer-completion-predicate)
+		 (eq 't (try-completion string
+					minibuffer-completion-table
+					minibuffer-completion-predicate))))
+
+	     ;; the result is the region to be highlighted
+	     region)))
+      (set-syntax-table old-syntax))))
+
+;; C source code scanner 
+(defvar c-statement-starting-keyword-regexpr
+  "\\(if\\|for\\|while\\|do\\|switch\\|break\\|continue\\)\\b")
+
+(defun c-boundaries (here)
+  (setq *last-thing* 'sexp)
+  (save-excursion
+    (goto-char here)
+    (let ((following-char (following-char))
+	  (preceding-char (preceding-char))
+	  aux)
+      (if (= (char-syntax following-char) ?w)
+	  (progn 
+	    (skip-chars-backward "a-zA-Z")
+	    (setq aux (point))
+	    (skip-chars-backward "\n\t ")
+	    (if (= (preceding-char) ?#)
+		(forward-char -1)
+	      (goto-char aux))))
+      (if (and (= following-char ?*)
+	       (= preceding-char ?/))
+	  (forward-char -1))
+      (if (and (= following-char ?/)
+	       (= preceding-char ?*))
+	  (forward-char -1))
+      (cond
+       ((= (following-char) ?#) (c-scan-preproc-macros))
+       ((looking-at "/\\*")	; begin comment
+	(let ((start (match-beginning 0)))
+	  (if (search-forward "*/" nil t)
+	      (thing-region start (match-end 0)))))
+       ((looking-at "\\*/")	; end comment
+	(let ((end (match-end 0)))
+	  (if (search-backward "/*" nil t)
+	      (thing-region (match-beginning 0) end))))
+       ((looking-at c-statement-starting-keyword-regexpr) ; if for while do etc
+	(thing-region (match-beginning 0)
+		      (c-forward-statement 
+		       (buffer-substring (match-beginning 1) (match-end 1)))))
+       ((looking-at "else\\b")
+	(thing-region (match-beginning 0) (c-forward-else)))
+       (t (if (= (char-syntax (following-char)) ?.)
+	      (thing-region here  (1+ here))
+	    (thing-boundaries here)))))))
+
+
+(defun c-scan-preproc-macros ()
+  (cond 
+   ((looking-at "^#[ \n\t]*include[ \n\t]*[<\"][^>\"]*[>\"]")   ; #include
+    (thing-region (match-beginning 0) (match-end 0)))
+   ((looking-at "^#[ \n\t]*\\(define\\|undef\\)") ; #define, #undef
+    (thing-region
+     (match-beginning 0) 
+     (progn 
+       (end-of-line)
+       (while (= (preceding-char) ?\\)
+	 (forward-line 1)
+	 (end-of-line))
+       (point))))
+   ;; #if, #ifdef, #ifndef, #else, #elif
+   ((looking-at "^#[ \n\t]*\\(if\\|ifdef\\|ifndef\\|else\\|elif\\)\\b")
+    (let ((start (match-beginning 0))
+	  (counter 1)
+	  match)
+      (goto-char (match-end 0))
+      (while (and (>= counter 1)
+		  (re-search-forward 
+		   "^#[ \n\t]*\\(if\\|ifdef\\|ifndef\\|endif\\)\\b"
+		   nil t))
+	(setq match 
+	      (buffer-substring (match-beginning 1) (match-end 1)))
+	(setq counter 
+	      (if (string= match "endif")
+		  (1- counter)
+		(1+ counter))))
+      (if (= counter 0)
+	  (thing-region start (match-end 0)))))
+   ((looking-at "^#[ \n\t]*endif\\b")   ; #endif
+    (let ((end (match-end 0))
+	  (counter 1)
+	  match)
+      (goto-char (match-beginning 0))
+      (while (and (>= counter 1)
+		  (re-search-backward
+		   "^#[ \n\t]*\\(if\\|ifdef\\|ifndef\\|endif\\)\\b"
+		   nil t))
+	(setq match 
+	      (buffer-substring (match-beginning 1) (match-end 1)))
+	(setq counter 
+	      (if (string= match "endif")
+		  (1+ counter)
+		(1- counter))))
+      (if (= counter 0)
+	  (thing-region (match-beginning 0) end))))))
+
+(defun c-skip-over-comment ()
+  (let ((aux (point)))
+    (skip-chars-forward "\n\t ")
+    (or (and (= (following-char) ?/)
+	     (= (char-after (1+ (point))) ?*)
+	     (search-forward "*/" nil t)
+	     (point))
+	(goto-char aux))))
+
+(defun c-forward-statement (&optional keyword)
+  (c-skip-over-comment)
+  (skip-chars-forward " \n\t")
+  (or keyword (setq keyword 
+		    (if (looking-at c-statement-starting-keyword-regexpr)
+			(buffer-substring 
+			 (match-beginning 1)
+			 (match-end 1)))))
+  (if keyword
+      (cond ((string= keyword "if")
+	     (c-forward-if))
+	    ((string= keyword "do")
+	     (c-forward-do-while))
+	    ((member keyword '("for" "while" "switch"))
+	     (c-forward-for/while/switch))
+	    ((member keyword '("break" "continue"))
+	     (c-forward-break/continue)))
+    (cond ((= (following-char) ?\{)
+	   (forward-list 1)
+	   (point))
+	  (t
+	   ;; Here I use that each C statement other then 
+	   ;; a bloc, if, while, for, do ... ends in a `;'
+	   (let (char)
+	     (catch 'exit
+	       (while t
+		 (if (eobp) (throw 'exit nil))
+		 (setq char (following-char))
+		 (cond ((= (char-syntax char) ?.) 
+			(forward-char 1)
+			(if (= char ?\;) (throw 'exit (point))))
+		       (t (forward-sexp 1)
+			  (skip-chars-forward " \n\t"))))))))))
+
+(defun c-forward-if ()
+  (let (aux)
+    (forward-word 1) ; if
+    (forward-list 1) 
+    (c-forward-statement)
+    (setq aux (point))
+    (skip-chars-forward "\n\t ")
+    (if (looking-at "else\\b")
+	(c-forward-else)
+	(goto-char aux))))
+
+(defun c-forward-else ()
+  (forward-word 1) ; else
+  (c-forward-statement))
+
+(defun c-forward-for/while/switch ()
+  (forward-word 1) ; for
+  (forward-list 1)
+  (c-forward-statement))
+
+(defun c-forward-do-while ()
+  (forward-word 1) ; do ... while
+  (c-forward-statement)
+  (c-forward-for/while/switch))
+
+(defun c-forward-switch ()
+  (forward-word 1) ; switch
+  (forward-list 2)
+  (point))
+
+(defun c-forward-break/continue ()
+  (forward-word 1) ; keyword
+  (c-skip-over-comment)
+  (skip-chars-forward "\n\t ")
+  (if (= (following-char) ?\;)
+      (goto-char (1+ (point)))))
+
+;; Tcl syntax scanner
+(defvar tcl-builtin-commands nil
+  "Alist of information about tcl syntax for the tcl-boundaries function.  
+An entry has the form 
+	\(<command-string> . <syntax description>\) 
+where 
+	<command-string>     is the name of a tcl command
+	<syntax description> is one of 
+            list of integers: the number of possible arguments
+	    t:		      any number of arguments")
+
+(defconst tcl-commands
+  '(
+    ("append"	. (2 . nil))
+    ("array"	. (2 . 3))
+    ("break"	. 0)
+    ("case" 	. 3)
+    ("catch"	. 1)
+    ("cd"	. 1)
+    ("close"	. 1)
+    ("concat"	. t)
+    ("continue"	. 0)
+    ("else" 	. (1 . nil))
+    ("elseif"	. (1 . nil))
+    ("eof"	. 1)
+    ("error"	. t)
+    ("eval"     . t)
+    ("exec"     . t)
+    ("exit"	. (0 . 1))
+    ("expr" 	. 1)
+    ("file"	. (2 . nil))
+    ("flush"	. 1)
+    ("for" 	. 4)
+    ("foreach" 	. 3)
+    ("format"	. (1 . nil))
+    ("gets"	. (1 . 2))
+    ("glob"	. t)
+    ("global" 	. (1 . nil))
+    ("history"	. t)
+    ("if" 	. (2 . nil))
+    ("incr" 	. (1 . 2))
+    ("info"	. (1 . 4))
+    ("join"	. (1 . 2))
+    ("lappend"	. (2 . nil))
+    ("lindex" 	. 2)
+    ("linsert"	. (3 . nil))
+    ("list"	. t)
+    ("llength" 	. 1)
+    ("lrange" 	. 3)
+    ("lreplace"	. (3 . nil))
+    ("lsearch" 	. 2)
+    ("lsort"	. 1)
+    ("open"	. (1 . 2))
+    ("proc" 	. 3)
+    ("puts"	. (1 . 3))
+    ("pwd"	. 0)
+    ("read"	. (1 . 2))
+    ("regexp"	. (2 . nil))
+    ("regsub"	. (4 . 6))
+    ("rename"	. 2)
+    ("return"	. (0 .1))
+    ("scan"	. (3 . nil))
+    ("seek"	. (2 . 3))
+    ("set" 	. (1 . 2))
+    ("source"	. 1)
+    ("split"	. (1 . 2))
+    ("string"	. (2 . 4))
+    ("tell"	. 1)
+    ("time"	. (1 .2))
+    ("trace"	. (1 . nil))
+    ("unknown"	. (1 . nil))
+    ("unset"	. (1 . nil))
+    ("uplevel"	. (1 . nil))
+    ("upvar"	. (2 . nil))
+    ("while" 	. 2)
+    ))
+
+(defconst tk-commands
+  '(("bind"	. 3)
+    ("button"	. t)
+    ("canvas"	. t)
+    ("frame"	. t)
+    ("label"	. t)
+    ("listbox"	. t)
+    ("menu"	. t)
+    ("menubutton"	. t)
+    ("pack"	. t)
+    ("scrollbar"	. t)
+    ("tree"	. t)
+    ("wm"		. t)
+    ))
+
+(defconst tcl-tk-commands
+  (nconc tcl-commands tk-commands))
+  
+(defconst tcl-tk-commands-regexp
+  (format "\\(%s\\\)\\W" (mapconcat 'car tcl-tk-commands "\\|")))
+
+(defun tcl-boundaries (here)
+  (save-excursion
+    (goto-char here)
+    (skip-chars-backward "a-z")
+    (if (looking-at 
+	 tcl-tk-commands-regexp)
+	(let* ((count 0) 
+	      (start (point))
+	      (keyword (buffer-substring
+			(match-beginning 1)
+			(match-end 1)))
+	      (syntax-description 
+	       (cdr (assoc keyword tcl-tk-commands))))
+	  (goto-char (match-end 0))
+	  (while (not (looking-at "[ \t]*[]\n;}]"))
+	    (setq count (1+ count))
+	    (tcl-forward-sexp1)
+	    ;; skipping over the parentheses of array expressions:
+	    (while (not (or (looking-at "[ \t]*[]\n;}]")
+			    (= (char-syntax (following-char)) ? )))
+	      (tcl-forward-sexp1)))
+
+	  (if (cond ((eq syntax-description t))
+		    ((integerp syntax-description) 
+		     (= syntax-description count))
+		    ((consp syntax-description)
+		     (and (<= (car syntax-description) count)
+			  (or (null (cdr syntax-description))
+			      (<= count (cdr syntax-description))))))
+	      (progn 
+		(message "`%s' matched."  keyword)
+		(thing-region start (point)))
+	    (progn 
+	      (message "wrong syntax: `%s'."  keyword)
+	      nil)))
+      (message "")
+      (thing-boundaries here))))
+
+(defun tcl-forward-sexp (&optional arg)
+  "Move forward across one balanced tcl expression.
+With argument, do it that many times."
+  (interactive "p")
+  (if (< arg 0) (error "negative argument not allowed"))
+  (or arg (setq arg 1))
+  (while (> arg 0)
+    (tcl-forward-sexp1)
+    (setq arg (1- arg))))
+
+(defun tcl-forward-sexp1 ()
+  (interactive "")  
+  (let ((start (point))
+	next-char syntax (first-scan t))
+    (setq next-char (following-char)
+	  syntax (char-syntax next-char))
+
+    (while (or (= next-char ?\;)
+	       (memq syntax '(? ?>)))
+      (forward-char 1)
+      (setq next-char (following-char)
+	    syntax (char-syntax next-char)))
+
+    (condition-case var
+	(catch 'exit 
+	  (while t
+	    (setq next-char (following-char)
+		  syntax (char-syntax next-char))
+	    (cond ((= next-char ?\;)
+		   (throw 'exit nil))
+		  ((memq syntax (if first-scan '(? ?>) '(? ?> ?\))))
+		   (throw 'exit nil))
+		  (t 
+		   (goto-char (or (scan-sexps (point) 1) 
+				  (point-max)))))
+	    (setq first-scan nil)))
+      (error (goto-char start)
+	     (error (car (cdr var)))))))
+
+;; (define-key tcl-mode-map "\M-\C-f" 'tcl-forward-sexp)
+
+(defun mode-motion-eval-func (eval-func)
+  (let ((old-buf (current-buffer))
+	(old-window (selected-window)))
+    (unwind-protect 
+	(let ((extent (or primary-selection-extent
+			  (and (extentp mode-motion-last-extent)
+			       (not (extent-property mode-motion-last-extent
+						     'detached))
+			       mode-motion-last-extent))))
+
+	  (if (and (extentp extent)
+		   (set-buffer (extent-buffer extent))
+		   (not 
+		    ;; zero length extents
+		    (= (extent-start-position extent)
+		       (extent-end-position extent))))
+
+	      (let* ((start (extent-start-position extent))
+		     (end (extent-end-position extent)))
+
+		(funcall eval-func start end))
+
+	    (error "No current primary or motion selection.")
+	    ))
+      (set-buffer old-buf)
+      (select-window old-window))))
+
+(defun mode-motion-eval-region ()
+  (interactive)
+  (mode-motion-eval-func 'eval-region))
+
+
+;; Motion highlight faces and initialization.
+
+(defun sect-handler (string)
+  "Return the symbol corresponding to the foo-STRING handler for this sect."
+  (intern-soft (concat (symbol-name mode-motion+-religion) string)))
+
+(defun mode-motion-init-handlers-according-to-religion (&optional forcep)
+  (interactive)
+  ;; Initialise default motion handlers depending on religious sect!
+  (let ((foo-thing (sect-handler "-thing"))
+	(foo-c (sect-handler "-c"))
+	(foo-LaTeX (sect-handler "-laTeX"))
+	(foo-line@ (sect-handler "-line@"))
+	(foo-vline@ (sect-handler "-vline@")))
+    (if forcep
+	(progn
+	  (setq default-motion-handler (find-motion-handler foo-thing))
+	  (set-mode-motion-handler 'emacs-lisp-mode foo-thing)
+	  (set-mode-motion-handler 'lisp-interaction-mode foo-thing)
+	  (set-mode-motion-handler 'c-mode foo-c)
+	  (set-mode-motion-handler 'c++-mode foo-c)
+	  (set-mode-motion-handler 'c++-c-mode foo-c)
+	  (set-mode-motion-handler 'tex-mode foo-LaTeX)
+	  (set-mode-motion-handler 'latex-mode foo-LaTeX)
+	  (set-mode-motion-handler 'Buffer-menu-mode foo-vline@)
+	  (set-mode-motion-handler 'Electric-Buffer-menu-mode foo-vline@)
+	  (set-mode-motion-handler 'gnus-Group-mode foo-vline@)
+	  (set-mode-motion-handler 'gnus-Subject-mode foo-vline@)
+	  (set-mode-motion-handler 'gnus-group-mode foo-vline@)
+	  (set-mode-motion-handler 'gnus-subject-mode foo-vline@)
+	  (set-mode-motion-handler 'gnus-summary-mode foo-vline@)
+	  (set-mode-motion-handler 'dired-mode foo-line@)
+	  (set-mode-motion-handler 'compilation-mode foo-line@)
+	  (set-mode-motion-handler 'occur-mode foo-line@)
+	  (set-mode-motion-handler 'tar-mode foo-vline@)
+	  (set-mode-motion-handler 'rmail-summary-mode foo-vline@)
+	  (set-mode-motion-handler 'vm-summary-mode (sect-handler "-line"))
+	  (set-mode-motion-handler 'tcl-mode (sect-handler "-tcl"))
+	  (set-mode-motion-handler 'texinfo-mode (sect-handler "-TeXinfo"))
+	  (set-mode-motion-handler 'cvs-mode (sect-handler "-cvs-line")))
+      (setq default-motion-handler
+	    (or default-motion-handler (find-motion-handler foo-thing)))
+      (or (get 'emacs-lisp-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'emacs-lisp-mode foo-thing))
+      (or (get 'lisp-interaction-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'lisp-interaction-mode foo-thing))
+      (or (get 'c-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'c-mode foo-c))
+      (or (get 'c++-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'c++-mode foo-c))
+      (or (get 'c++-c-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'c++-c-mode foo-c))
+      (or (get 'tex-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'tex-mode foo-LaTeX))
+      (or (get 'latex-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'latex-mode foo-LaTeX))
+      (or (get 'Buffer-menu-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'Buffer-menu-mode foo-vline@))
+      (or (get 'Electric-Buffer-menu-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'Electric-Buffer-menu-mode foo-vline@))
+      (or (get 'gnus-Group-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'gnus-Group-mode foo-vline@))
+      (or (get 'gnus-Subject-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'gnus-Subject-mode foo-vline@))
+      (or (get 'gnus-group-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'gnus-group-mode foo-vline@))
+      (or (get 'gnus-subject-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'gnus-subject-mode foo-vline@))
+      (or (get 'gnus-summary-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'gnus-summary-mode foo-vline@))
+      (or (get 'dired-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'dired-mode foo-line@))
+      (or (get 'compilation-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'compilation-mode foo-line@))
+      (or (get 'occur-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'occur-mode foo-line@))
+      (or (get 'tar-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'tar-mode foo-vline@))
+      (or (get 'rmail-summary-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'rmail-summary-mode foo-vline@))
+      (or (get 'vm-summary-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'vm-summary-mode (sect-handler "-line")))
+      (or (get 'tcl-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'tcl-mode (sect-handler "-tcl")))
+      (or (get 'texinfo-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'texinfo-mode (sect-handler "-TeXinfo")))
+      (or (get 'cvs-mode 'mode-motion-handler)
+	  (set-mode-motion-handler 'cvs-mode (sect-handler "-cvs-line"))))))
+
+;; Null Handlers (for disabling motion highlighting)
+(defun thing-null (here) nil)
+(make-motion-handler 'no-thing 'thing-null)
+(make-motion-handler 'no-c 'thing-null)
+(make-motion-handler 'no-laTeX 'thing-null)
+(make-motion-handler 'no-line 'thing-null)
+(make-motion-handler 'no-line@ 'thing-null)
+(make-motion-handler 'no-vline 'thing-null)
+(make-motion-handler 'no-vline@ 'thing-null)
+(make-motion-handler 'no-tcl 'thing-null)
+(make-motion-handler 'no-TeXinfo 'thing-null)
+(make-motion-handler 'no-cvs-line 'thing-null)
+
+(defun mode-motion-init ()
+  "enable mode-motion+ package"
+  (interactive)
+
+(setq mode-motion-last-extent nil)
+  
+(global-set-key '(meta button2) 'mode-motion-copy)
+(global-set-key '(meta shift button2) 'mode-motion-move)
+(global-set-key '(meta control button2) 'mode-motion-kill)
+(global-set-key '(meta control shift button2) 'mode-motion-copy-as-kill)
+(global-set-key '(meta control symbol button2) 'mode-motion-copy-as-kill)
+
+(if mode-motion-setup-cut-and-paste-bindings
+    (progn 
+      (global-set-key 'f16 'mode-motion-copy-as-kill) ; Copy
+      (global-set-key 'f18 'yank)	              ; Paste
+      (global-set-key 'f20 'mode-motion-kill)))       ; Cut
+
+;; I don't want the thing-boundaries function select whitespaces 
+(setq thing-report-whitespace nil thing-report-char-p nil)
+
+;; bold motion face (bold, if this is not the default, unbold otherwise)
+(if (find-face 'motion-bold)
+    ()
+  (make-face 'motion-bold)
+  (make-face-bold 'motion-bold)
+  (or (face-differs-from-default-p 'motion-bold)
+      (make-face-unbold 'motion-bold)))
+
+;; an underline face
+(if (find-face 'motion-underline)
+    ()
+  (make-face 'motion-underline)
+  (set-face-underline-p 'motion-underline t))
+
+;; an inverted face
+(if (find-face 'motion-inverted)
+    ()
+  (make-face 'motion-inverted)
+  (make-face-bold 'motion-inverted)
+  (invert-face 'motion-inverted))
+
+(if (find-face 'motion-gray)
+    ()
+  (make-face 'motion-gray)
+  (set-face-background-pixmap 'motion-gray "gray1.xbm"))
+ 
+;; Motion Handlers
+
+;; Special Minibuffer handler
+
+(make-motion-handler 'minibuffer 'minibuffer-selection-boundaries 'highlight t nil)
+
+;; Things
+(make-motion-handler 'bold-thing 'thing-boundaries 'motion-bold)
+(make-motion-handler 'gray-thing 'thing-boundaries 'motion-gray)
+(make-motion-handler 'highlight-thing 'thing-boundaries 'highlight)
+(make-motion-handler 'invert-thing 'thing-boundaries 'motion-inverted)
+(make-motion-handler 'underline-thing 'thing-boundaries 'motion-underline)
+
+;; Lines
+(make-motion-handler 'bold-line 'line-boundaries 'motion-bold)
+(make-motion-handler 'gray-line 'line-boundaries 'motion-gray)
+(make-motion-handler 'highlight-line 'line-boundaries 'highlight)
+(make-motion-handler 'invert-line 'line-boundaries 'motion-inverted)
+(make-motion-handler 'underline-line 'line-boundaries 'motion-underline)
+(make-motion-handler 'bold-line@ 'line-boundaries 'motion-bold t t)
+(make-motion-handler 'gray-line@ 'line-boundaries 'motion-gray nil t)
+(make-motion-handler 'highlight-line@ 'line-boundaries 'highlight nil t)
+(make-motion-handler 'invert-line@ 'line-boundaries 'motion-inverted nil t)
+(make-motion-handler 'underline-line@ 'line-boundaries 'motion-underline nil t)
+
+;; Visible text of line
+(make-motion-handler 'bold-vline 'visible-line-boundaries 'motion-bold)
+(make-motion-handler 'gray-vline 'visible-line-boundaries 'motion-gray)
+(make-motion-handler 'highlight-vline 'visible-line-boundaries 'highlight)
+(make-motion-handler 'invert-vline 'visible-line-boundaries 'motion-inverted)
+(make-motion-handler 'underline-vline 'visible-line-boundaries 'motion-underline)
+(make-motion-handler 'bold-vline@ 'visible-line-boundaries 'motion-bold t t)
+(make-motion-handler 'gray-vline@ 'visible-line-boundaries 'motion-gray nil t)
+(make-motion-handler 'highlight-vline@ 'visible-line-boundaries 'highlight nil t)
+(make-motion-handler 'invert-vline@ 'visible-line-boundaries 'motion-inverted nil t)
+(make-motion-handler 'underline-vline@ 'visible-line-boundaries 'motion-underline nil t)
+
+;; CVS lines
+(make-motion-handler 'bold-cvs-line 'cvs-line-boundaries 'motion-bold)
+(make-motion-handler 'gray-cvs-line 'cvs-line-boundaries 'motion-gray)
+(make-motion-handler 'highlight-cvs-line 'cvs-line-boundaries 'highlight)
+(make-motion-handler 'invert-cvs-line 'cvs-line-boundaries 'motion-inverted)
+(make-motion-handler
+ 'underline-cvs-line 'cvs-line-boundaries 'motion-underline)
+
+;; (La)TeX 
+(make-motion-handler 'bold-LaTeX 'latex-boundaries 'motion-bold)
+(make-motion-handler 'gray-LaTeX 'latex-boundaries 'motion-gray)
+(make-motion-handler 'highlight-LaTeX 'latex-boundaries 'highlight)
+(make-motion-handler 'invert-LaTeX 'latex-boundaries 'motion-inverted)
+(make-motion-handler 'underline-LaTeX 'latex-boundaries 'motion-underline)
+
+;; TeXinfo
+(make-motion-handler 'bold-TeXinfo 'texinfo-boundaries 'motion-bold)
+(make-motion-handler 'gray-TeXinfo 'texinfo-boundaries 'motion-gray)
+(make-motion-handler 'highlight-TeXinfo 'texinfo-boundaries 'highlight)
+(make-motion-handler 'invert-TeXinfo 'texinfo-boundaries 'motion-inverted)
+(make-motion-handler 'underline-TeXinfo 'texinfo-boundaries 'motion-underline)
+
+;; C and C++
+(make-motion-handler 'bold-c 'c-boundaries 'motion-bold)
+(make-motion-handler 'gray-c 'c-boundaries 'motion-gray)
+(make-motion-handler 'highlight-c 'c-boundaries 'highlight)
+(make-motion-handler 'invert-c 'c-boundaries 'motion-inverted)
+(make-motion-handler 'underline-c 'c-boundaries 'motion-underline)
+
+;; Tcl/Tk
+(make-motion-handler 'bold-tcl 'tcl-boundaries 'motion-bold)
+(make-motion-handler 'gray-tcl 'tcl-boundaries 'motion-gray)
+(make-motion-handler 'highlight-tcl 'tcl-boundaries 'highlight)
+(make-motion-handler 'invert-tcl 'tcl-boundaries 'motion-inverted)
+(make-motion-handler 'underline-tcl 'tcl-boundaries 'motion-underline)
+
+;; mouse tracker
+(make-motion-handler 'track-mouse@ 'char-boundaries nil nil t)
+(make-motion-handler 'highlight-char 'char-boundaries 'highlight)
+
+;; augment the basic mouse motion handler (if any)
+(setq-default mode-motion-hook 
+	      (if (listp mode-motion-hook)
+		  (if (memq #'mode-motion+-highlight mode-motion-hook)
+		      mode-motion-hook
+		    (append mode-motion-hook (list #'mode-motion+-highlight)))
+		(list mode-motion-hook #'mode-motion+-highlight)))
+
+(or mode-motion+-religion 
+    (setq mode-motion+-religion (if (x-display-color-p) 'underline 'invert)))
+
+(add-menu '("Options") (car mode-motion+-options-menu)
+	  (cdr mode-motion+-options-menu)
+	  "Paren Highlighting")
+
+;; shut your eyes, this is a kludge. I didn't have time to find/write
+;; a function to do this.
+(or (member ["Eval Motion Region" mode-motion-eval-region t]
+	    lisp-interaction-mode-popup-menu)
+    (and (setq lisp-interaction-mode-popup-menu
+	       (copy-sequence lisp-interaction-mode-popup-menu))
+	 (setcdr (nthcdr 1 lisp-interaction-mode-popup-menu)
+		 (cons ["Eval Motion Region" mode-motion-eval-region t]
+		       (nthcdr 2 lisp-interaction-mode-popup-menu)))))
+
+(or (member ["Eval Motion Region" mode-motion-eval-region t]
+	    emacs-lisp-mode-popup-menu)
+    (and (setq emacs-lisp-mode-popup-menu
+	       (copy-sequence emacs-lisp-mode-popup-menu))
+	 (setcdr (nthcdr 3 emacs-lisp-mode-popup-menu)
+		 (cons ["Eval Motion Region" mode-motion-eval-region t]
+		       (nthcdr 4 emacs-lisp-mode-popup-menu)))))
+
+;; Clear the last active motion extent when leaving a frame.
+(if (boundp 'mouse-leave-frame-hook)
+    (add-hook 'mouse-leave-frame-hook 'mode-motion-clear-last-extent)
+  (add-hook 'mouse-leave-screen-hook 'mode-motion-clear-last-extent))
+	       
+(run-hooks 'mode-motion+-load-hook)
+(mode-motion-init-handlers-according-to-religion)
+
+(if (interactive-p) (message "mode-motion+ enabled")))
+
+(if (and (not purify-flag)
+	 (or (not (boundp 'opt-mode-motion+)) opt-mode-motion+))
+    (mode-motion-init))
+
+(provide 'mode-motion+)
+;; end mode-motion+