home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / epoch / enhanced-mouse.el < prev    next >
Encoding:
Text File  |  1991-03-30  |  22.8 KB  |  653 lines

  1. ; Date: Tue, 9 Oct 90 14:48:23 EDT
  2. ; From: Ken Laprade <laprade@trantor.harris-atd.com>
  3. ; Subject: mouse.el enhancements and mouse-help.el
  4. ; The changes to epoch::coords-to-point in mouse.c that I sent in last month
  5. ; allow the mouse::handler to distinguish between button events actually in a
  6. ; window, on a mode line, or in the (inactive) minibuffer area.  Here is the
  7. ; mouse.el that I am now using.  I have added support for separate
  8. ; mouse-map's for each of these three areas.  There are also some functions
  9. ; and sample mouse bindings for things that do not require motion (those are
  10. ; in motion.el).
  11. ; I have also included mouse-help.el.  This contains describe-mouse and
  12. ; describe-mouse-briefly, which accept a mouse press and print documentation
  13. ; on its binding, and mouse-helper, which pops up a small screen listing the
  14. ; mouse::global-map bindings.  All expect to be used with my version of
  15. ; mouse.el.
  16. ; -- 
  17. ; Ken Laprade            INTERNET: laprade@trantor.harris-atd.com
  18. ; Harris Corporation         Usenet:  ...!uunet!x102a!trantor!laprade
  19. ; PO Box 37, MS 3A/1912        Voice: (407)727-4433
  20. ; Melbourne, FL 32902        FAX: (407)729-2537
  21. ;;; Copyright (C) 1990  Alan M. Carroll
  22. ;;;
  23. ;;; This file is for use with Epoch, a modified version of GNU Emacs.
  24. ;;; Requires Epoch 3.2 or later.
  25. ;;;
  26. ;;; This code is distributed in the hope that it will be useful,
  27. ;;; bute WITHOUT ANY WARRANTY. No author or distributor accepts
  28. ;;; responsibility to anyone for the consequences of using this code
  29. ;;; or for whether it serves any particular purpose or works at all,
  30. ;;; unless explicitly stated in a written agreement.
  31. ;;;
  32. ;;; Everyone is granted permission to copy, modify and redistribute
  33. ;;; this code, but only under the conditions described in the
  34. ;;; GNU Emacs General Public License, except the original author nor his
  35. ;;; agents are bound by the License in their use of this code.
  36. ;;; (These special rights for the author in no way restrict the rights of
  37. ;;;  others given in the License or this prologue)
  38. ;;; A copy of this license is supposed to have been given to you along
  39. ;;; with Epoch so you can know your rights and responsibilities. 
  40. ;;; It should be in a file named COPYING.  Among other things, the
  41. ;;; copyright notice and this notice must be preserved on all copies. 
  42. ;;;
  43. (provide 'epoch-mouse)
  44. (require 'cl)
  45. (require 'epoch-button "button")
  46. ;;;
  47. ;;; Mouse event handler - extended by Ken Laprade <laprade@trantor.harris-atd.com>. 
  48. ;;; Mouse events are set to come in on the event Q, and are then dispatched.
  49. ;;; For each button, there are two 16-element tables, each entry being a list of
  50. ;;; handler functions. The table is indexed by the modifier&transistion state.
  51. ;;; One table is used for button presses in the mode line and the other for
  52. ;;; presses in the window proper.
  53. ;;;
  54. ;;; There are also tables for mouse presses in the minibuffer when it is
  55. ;;; not active.  Functions in this map are always called with a nil argument.
  56. ;;;
  57. (defconst mouse::button-size 16)
  58. (defconst mouse::table-size (* 3 3 mouse::button-size))
  59. (defvar mouse::global-map (make-vector mouse::table-size nil))
  60. (defvar mouse::local-map nil)
  61. (make-variable-buffer-local 'mouse::local-map)
  62. ;;; --------------------------------------------------------------------------
  63. ;;;
  64. ;;; define the button states
  65. ;;;
  66. (defvar shift-mod-mask 1 "Mask for Shift modifier down")
  67. (defvar shift-lock-mod-mask 2 "Mask for Shift Lock modifier down")
  68. (defvar control-mod-mask 4 "Mask for Control modifier down")
  69. (defvar meta-mod-mask 8 "Mask for Meta (mod1) modifier down")
  70. (defvar keyboard-mod-mask
  71.   (+ shift-mod-mask control-mod-mask meta-mod-mask)
  72.   "Mask for any of the keyboard modifiers"
  73. )
  74.  
  75. (defvar mouse1-mask 256 "Mask for mouse button 1 down")
  76. (defvar mouse2-mask 512 "Mask for mouse button 2 down")
  77. (defvar mouse3-mask 1024 "Mask for mouse button 3 down")
  78. (defvar mouse4-mask 2048 "Mask for mouse button 4 down")
  79. (defvar mouse5-mask 4096 "Mask for mouse button 5 down")
  80. (defvar mouse-any-mask (logior mouse1-mask mouse2-mask mouse3-mask mouse4-mask mouse5-mask)
  81. "Mask for any of the mouse buttons")
  82. ;;;
  83. ;;; the button/mod constant definitions
  84. ;;;
  85. (defconst mouse-window 0)
  86. (defconst mouse-left 0)
  87. (defconst mouse-middle 1)
  88. (defconst mouse-right 2)
  89. (defconst mouse-mode 3)
  90. (defconst mouse-mode-left 3)
  91. (defconst mouse-mode-middle 4)
  92. (defconst mouse-mode-right 5)
  93. (defconst mouse-minibuf 6)
  94. (defconst mouse-minibuf-left 6)
  95. (defconst mouse-minibuf-middle 7)
  96. (defconst mouse-minibuf-right 8)
  97.  
  98. (defconst mouse-down 0)
  99. (defconst mouse-up 1)
  100.  
  101. (defconst mouse-shift 2)
  102. (defconst mouse-shift-up (+ mouse-shift mouse-up))
  103. (defconst mouse-control 4)
  104. (defconst mouse-control-up (+ mouse-control mouse-up))
  105. (defconst mouse-control-shift (+ mouse-shift mouse-control))
  106. (defconst mouse-control-shift-up (+ mouse-control-shift mouse-up))
  107. (defconst mouse-meta 8)
  108. (defconst mouse-meta-up (+ mouse-meta mouse-up))
  109. (defconst mouse-meta-shift (+ mouse-shift mouse-meta))
  110. (defconst mouse-meta-shift-up (+ mouse-meta-shift mouse-up))
  111. (defconst mouse-meta-control (+ mouse-meta mouse-control))
  112. (defconst mouse-meta-control-up (+ mouse-meta-control mouse-up))
  113. (defconst mouse-meta-control-shift (+ mouse-shift mouse-control mouse-meta))
  114. (defconst mouse-meta-control-shift-up (+ mouse-meta-control-shift mouse-up))
  115. ;;; --------------------------------------------------------------------------
  116. ;;; handler installation, etc.
  117. (defun mouse::verify-arguments (button modstate)
  118.   (when (or (< button mouse-left) (> button mouse-minibuf-right))
  119.     (error "Button specifier out of range")
  120.   )
  121.   (when (or (< modstate 0) (>= modstate mouse::button-size))
  122.     (error "Button modifier out of range")
  123.   )
  124. )
  125. ;;; --------------------------------------------------------------------------
  126. ;;;
  127. ;;; This is called for all the mouse events. I'm just going to assume that
  128. ;;; every function wants to know where the mouse event was in point/buffer
  129. ;;; terms, and is going to go through this effort anyway.
  130. ;;;
  131. (defun mouse::xy-to-point (arg)
  132. "Convert an (X Y) list to point. Assumes that the current window is correct. Returns nil if (X Y) is not in the selected window"
  133.   (let
  134.     (
  135.       (rel-coordinate (coordinates-in-window-p arg (selected-window)))
  136.     )
  137.     (if rel-coordinate
  138.       (save-excursion
  139.     (move-to-window-line (cadr rel-coordinate))
  140.     (let ( (h (window-hscroll)) )
  141.       (move-to-column
  142.         (+ 
  143.           (if (> h 0) (- h 1) h) ;deal with scrolled lines
  144.           (current-column)    ;deal with wrapped lines
  145.           (car rel-coordinate)
  146.         )
  147.       )
  148.     )
  149.     (point)            ;return value
  150.       )
  151.       nil                ;return for XY not in window
  152.     )
  153.   )
  154. )
  155.  
  156. ;;;
  157. (defun mouse::convert-xy-screen (arg scr)
  158. "Convert an (X Y) list and SCREEN into a list of (POINT BUFFER WINDOW SCREEN)"
  159.   (let
  160.     (
  161.       (cw (selected-window))
  162.       (result nil)
  163.     )
  164.     (unwind-protect
  165.       (progn
  166.     (epoch::select-screen scr)    ;bypass clever stuff
  167.     ;; first, find the window the point was in
  168.     (let
  169.       (
  170.         (start-w (selected-window))
  171.         (done nil)
  172.         (w (selected-window))
  173.         (rel-coordinate nil)
  174.       )
  175.       (while
  176.         (and
  177.           (not done)
  178.           (null (setq rel-coordinate (coordinates-in-window-p arg w)))
  179.         )
  180.         (setq w (next-window w))
  181.         (if (eq w start-w) (setq done t))
  182.       )
  183.       (when rel-coordinate
  184.         (select-window w)
  185.         ;; the right window is selectioned, and we have the window-relative    
  186.     ;; co-ordinates. we can finally calculate point!
  187.         (unwind-protect
  188.           (save-excursion
  189.         (move-to-window-line (cadr rel-coordinate))
  190.         (let ( (h (window-hscroll)) )
  191.           (move-to-column
  192.             (+ 
  193.               (if (> h 0) (- h 1) h) ;deal with scrolled lines
  194.               (current-column)    ;deal with wrapped lines
  195.               (car rel-coordinate)
  196.             )
  197.           )
  198.         )
  199.         (setq result
  200.           (list (point) (current-buffer) w (current-screen))
  201.         )
  202.           )
  203.           ;; CLEAN-UP
  204.           (select-window start-w)    ;restore in case of window switch
  205.         )
  206.       )
  207.     )
  208.       )
  209.       ;; CLEAN-UP
  210.       (select-window cw)        ;; this will force the screen back too!
  211.     )
  212.     result
  213.   )
  214. )
  215. ;;; --------------------------------------------------------------------------
  216. ;;;
  217. (defvar mouse::down-buffer nil "Buffer where the mouse last was pressed.")
  218. (defvar mouse::down-number-offset 0
  219.   "Where the mouse last was pressed (window, mode, minibuf).")
  220. (defvar mouse::event-data nil
  221.   "Raw data value mouse::handler was called with (press/release x y button mod-state).")
  222. (defvar mouse::x 0 "X screen position of mouse, just in case somebody wants it.")
  223. (defvar mouse::y 0 "Y screen position of mouse, just in case somebody wants it.")
  224. (defvar mouse::last-spot nil
  225.   "Mouse data value of last event (point buffer window screen).")
  226. (defvar mouse::clicks 0
  227.   "Number of times mouse was pressed and released in the same place.")
  228. (defvar mouse::clicking nil "t if mouse hasn't moved and same button is being pressed.")
  229.  
  230. (defun mouse::handler (type value scr)
  231.   (let*
  232.     (
  233.       (number (nth 3 value))
  234.       (edge (nth 0 value))
  235.       (modstate (nth 4 value))
  236.       (epoch::event-handler-abort nil)    ;prevent lossage
  237.       (arg (epoch::coords-to-point (nth 1 value) (nth 2 value) scr))
  238.       (buffer (and arg (nth 1 arg)))
  239.       ;; Find which button table.  We want to stay in the same set of tables
  240.       ;; (window, mode, minibuf) as any down press.
  241.       (number-offset (if mouse::down-buffer
  242.              mouse::down-number-offset
  243.                (if (and (eq (nth 2 arg) (minibuffer-window))
  244.                 (= (minibuffer-depth) 0))
  245.                mouse-minibuf
  246.              (if (null (car arg))
  247.                  mouse-mode
  248.                0))))
  249.     )
  250.  
  251.     ;; Minibuf presses get no args.
  252.     (if (= number-offset mouse-minibuf)
  253.     (setq arg nil))
  254.  
  255.     ;; Count clicks as a convenience for some functions.
  256.     (setq mouse::clicking
  257.       (and
  258.         (equal (nth 3 mouse::event-data) number)
  259.     (equal mouse::down-number-offset number-offset)
  260.         (or edge (equal (logand (nth 4 mouse::event-data) keyboard-mod-mask)
  261.             (logand modstate keyboard-mod-mask)))
  262.     (equal mouse::last-spot arg)
  263.         (equal mouse::x (nth 1 value))
  264.         (equal mouse::y (nth 2 value))
  265.       )
  266.     )
  267.     (if mouse::clicking
  268.     (or edge
  269.       ;; count click on button up.
  270.       (setq mouse::clicks (1+ mouse::clicks))
  271.     )
  272.       (setq mouse::clicks 0)
  273.     )
  274.     (setq mouse::event-data value)
  275.     (setq mouse::x (nth 1 value))
  276.     (setq mouse::y (nth 2 value))
  277.  
  278.     (setq number (+ number number-offset))
  279. ;    (message "clicks:%d number:%d scr:%s value:%s arg:%s" mouse::clicks number scr value arg)
  280.  
  281.     ;; find the handler list and try to dispatch
  282.     (let*
  283.       (
  284.         (index
  285.       (+
  286.         (if edge mouse-down mouse-up)
  287.         (if (/= 0 (logand modstate shift-mod-mask)) mouse-shift 0)
  288.         (if (/= 0 (logand modstate control-mod-mask)) mouse-control 0)
  289.         (if (/= 0 (logand modstate meta-mod-mask)) mouse-meta 0)
  290.         (* mouse::button-size ( - number 1 ))
  291.       )
  292.     )
  293.     (map
  294.       (if (and mouse::down-buffer (not edge))
  295.           ;; force release into press buffer, for simulated grab
  296.           (symbol-buffer-value 'mouse::local-map mouse::down-buffer)
  297.         ;; ELSE if there's an arg, use the arg buffer
  298.         (and arg (symbol-buffer-value 'mouse::local-map buffer))
  299.       )
  300.     )
  301.     (handler
  302.       (or
  303.         (and (vectorp map) (aref map index))
  304.         (aref mouse::global-map index)
  305.       )
  306.     )
  307.       )
  308.       ;; Record down circumstances for next event.
  309.       (setq mouse::down-buffer (and edge buffer))
  310.       (if edge
  311.       (setq mouse::down-number-offset number-offset))
  312.  
  313.       ;; Do it.
  314.       (when (and handler (functionp handler))
  315.         (funcall handler arg)
  316.       )
  317.     )
  318.     (setq mouse::last-spot arg)
  319.   )
  320. )
  321. ;;; --------------------------------------------------------------------------
  322. (defmacro mouse::index (button modstate)
  323.   (`
  324.     (+ (, modstate) (* (, button) (, mouse::button-size)))
  325.   )
  326. )
  327. ;;;
  328. (defun copy-mouse-map (from to)
  329.   (when (null to) (setq to (make-vector mouse::table-size nil)))
  330.   (let ( (i 0) )
  331.     (while (< i mouse::table-size)
  332.       (aset to i (aref from i))
  333.       (incf i)
  334.     )
  335.   )
  336.   to                    ; return value
  337. )
  338. ;;;
  339. (defun create-mouse-map (&optional source-map)
  340.   (if (vectorp source-map)
  341.     (copy-mouse-map source-map nil)
  342.     (make-vector mouse::table-size nil)
  343.   )
  344. )
  345. ;;;
  346. (defun local-set-mouse (button modstate function)
  347.   (mouse::verify-arguments button modstate)
  348.   (when (null mouse::local-map)
  349.     (setq mouse::local-map (create-mouse-map mouse::global-map))
  350.   )
  351.   (aset mouse::local-map (mouse::index button modstate) function)
  352. )
  353. ;;;
  354. (defun global-set-mouse (button modstate function)
  355. "Set the global mouse map to have BUTTON with MODIFIER call FUNCTION"
  356.   (mouse::verify-arguments button modstate)
  357.   (aset mouse::global-map (mouse::index button modstate) function)
  358. )
  359. ;;;
  360. (defun define-mouse (map button modstate function)
  361. "Set an entry in the MAP for BUTTON and MODIFIER to FUNCTION"
  362.   (when (not (vectorp map)) (error "Map must be a vector"))
  363.   (aset map (mouse::index button modstate) function)
  364. )
  365. ;;;
  366. (defun use-local-mouse-map (map &optional buffer)
  367.   (when (not (vectorp map)) (error "Invalid mouse map"))
  368.   (if (bufferp buffer)
  369.     (save-excursion
  370.       (set-buffer buffer)
  371.       (setq mouse::local-map map)
  372.     )
  373.     (setq mouse::local-map map)
  374.   )
  375. )
  376. ;;;
  377. (defun kill-local-mouse-map (&option buffer)
  378. "Remove the local mouse map for the option BUFFER (if nil, current buffer)"
  379.   (if (bufferp buffer)
  380.     (save-excursion
  381.       (set-buffer buffer)
  382.       (kill-local-variable 'mouse::local-map)
  383.     )
  384.     (kill-local-variable 'mouse::local-map)
  385.   )
  386. )
  387. ;;; --------------------------------------------------------------------------
  388. (defun mouse::set-point (arg)
  389.   "Select Epoch window mouse is on, and move point to mouse position."
  390.   (select-screen (nth 3 arg))
  391.   (if (nth 2 arg) (select-window (nth 2 arg)))
  392.   (if (car arg) (goto-char (car arg)))
  393. )
  394. ;;;
  395. (defun mouse::copy-button (button &optional kill)
  396.   "Copy the text in the BUTTON into the X cut buffer and into the Epoch kill ring.
  397. If button does not exist, the X cut buffer is emptied."
  398.   (if (buttonp button)
  399.     (let
  400.       (
  401.         (beg (epoch::button-start button))
  402.     (end (epoch::button-end button))
  403.       )
  404.       (if (null beg) (setq beg 0))
  405.       (if (null end) (setq end 0))
  406.       (epoch::store-cut-buffer (buffer-substring beg end))
  407.       (if (/= beg end)
  408.     (if kill
  409.         (delete-region beg end)
  410.       (copy-region-as-kill beg end)
  411.         )
  412.       )
  413.     )
  414.     (epoch::store-cut-buffer "")
  415.   )
  416. )
  417. ;;;
  418. (defun mouse::paste-cut-buffer (arg)
  419.     (let ( (buff (nth 1 arg)) )
  420.       (when (and buff (bufferp buff))
  421.       (save-excursion
  422.     (set-buffer (nth 1 arg))
  423.     (goto-char (car arg))
  424.     (insert (epoch::get-cut-buffer))
  425.     (undo-boundary)
  426.     (setq last-command nil)
  427.       )
  428.     )
  429.   )
  430. )
  431. ;;; --------------------------------------------------------------------------
  432. ;;;
  433. ;;; Install things
  434. ;;;
  435. (push-event 'button 'mouse::handler)
  436. (setq epoch::mouse-events t)
  437. ;;;
  438. ;;; --------------------------------------------------------------------------
  439. ;;; Macros useful for small mouse bindings that aren't worth defining
  440. ;;; a separate function:
  441. (defmacro mousefun (&rest body)
  442.   (`
  443.    (function (lambda (arg) (,@ body )))))
  444.  
  445. (defmacro mousefun-set-point (&rest body)
  446.   (`
  447.    (function (lambda (arg) (mouse::set-point arg) (,@ body )))))
  448. ;;; --------------------------------------------------------------------------
  449. ;;; Some mouse functions that do not require motion:
  450.  
  451. (fset 'mouse-set-point 'mouse::set-point)
  452.  
  453. (defun abort-isearch () "Abort any isearch in progress."
  454.   (condition-case err
  455.       (throw 'search-done t)
  456.     (no-catch nil)))
  457.  
  458. (defun mouse-set-spot (arg)
  459.   "Set point at mouse.  With double-click, set mark there as well.
  460. Blinks matching paren if sitting after one.  Intended to be bound
  461. to a window down button."
  462.   (let ((buf (current-buffer))
  463.     (p (point)))
  464.     (mouse::set-point arg)
  465.     (if (and (equal p (point))
  466.          (equal buf (current-buffer)))
  467.     (if (and (= mouse::clicks 1)
  468.          (not (eq (mark) (point))))
  469.         (push-mark))
  470.       (setq mouse::clicks 0))
  471.     (if (eq (char-syntax (preceding-char)) ?\))
  472.       (blink-matching-open)))
  473.   (abort-isearch))
  474.  
  475. (defun mouse-select-buffer (arg)
  476.   "Select the window indicated with the mouse.  With drag, adjust
  477. the size of the window (either horizontally or vertically).
  478. With double click, save point with mark-location-form and bury buffer.
  479. Intended to be bound to a mode-line up button."
  480.   (let ((window (selected-window)))
  481.     (mouse::set-point mouse::last-spot)
  482.     (cond ((= mouse::clicks 0)
  483.        (let ((growth (- mouse::y (nth 1 (window-edges)) (window-height) -1)))
  484.          (if (= growth 0)
  485.          ;; No vertical motion, must be horizontal motion.
  486.          (or (= (window-width) (screen-width))
  487.              (enlarge-window-horizontally (- mouse::x (car (window-edges)) (window-width))))
  488.            (or (one-window-p)
  489.            (enlarge-window growth))))
  490.        ;; Don't change selected window when adjusting size.
  491.        (if (window-point window) (select-window window)))
  492.       ((> mouse::clicks 1)
  493.        (if (boundp 'mark-location-form) (eval mark-location-form))
  494.        (bury-buffer)))))
  495.  
  496. (defun mouse-vscroll (arg)
  497.   "Vertical scroll mouse spot to top of window if it mouse in the lower half
  498. of the window or to the bottom of the window if mouse is in the upper half of
  499. the window.  With a drag, scroll the line at the down press to the mouse
  500. location at the up press.  This should be bound to an up button."
  501.        (mouse::set-point mouse::last-spot)
  502.            (let ((window-line (- mouse::y (nth 1 (window-edges)))))
  503.              (recenter (cond ((< mouse::clicks 1)
  504.                       (min (max window-line 0) (- (window-height) 2)))
  505.                      ((< window-line (/ (window-height) 2))
  506.                       -1)
  507.                      (t 0)))))
  508.  
  509. (defun mouse-yank (arg)
  510.   "Set point at mouse and yank text from kill ring."
  511.   (mouse::set-point arg)
  512.   (if (> mouse::clicks 0)        ; Abort if mouse moved.
  513.       (progn
  514.     (undo-boundary)
  515.     (yank)
  516.     (setq last-command 'yank)
  517.     (abort-isearch))))
  518.  
  519. (defun mouse-split-window (arg)
  520.   "Split the window vertically at the spot the mouse is clicked."
  521.   (select-screen (nth 3 arg))
  522.   (select-window (nth 2 arg))
  523.   (let ((height (if (car arg)
  524.             (count-lines (window-start) (car arg))
  525.           (/ (window-height) 2))))
  526.     (if (or (> window-min-height height)
  527.         (> window-min-height (- (window-height) height)))
  528.     (error "Window size is too small")
  529.       (split-window-vertically height))))
  530.  
  531. (defvar highlight-attribute (reserve-attribute) "Attribute for highlight buttons.")
  532. (set-attribute-global highlight-attribute (background) (foreground) (background) (foreground))
  533. (setq epoch::buttons-modify-buffer nil)
  534. (defvar grab-button nil "Highlighted region for mouse grab functions.")
  535.  
  536. (defun mouse-select-thing (arg)
  537.   "Highlight thing at mouse ARG.  It will be grab-button.  This function
  538. is intended to be bound to a down button.  The corresponding up button
  539. should probably delete grab-button."
  540.   (require 'thing)
  541.   (save-excursion
  542.     (set-buffer (nth 1 arg))
  543.     (let* ((place (thing-boundaries (car arg)))
  544.        (start (car place))
  545.        (end (cdr place)))
  546.       (delete-button grab-button)
  547.       (setq grab-button (add-button start end highlight-attribute))))
  548.   (abort-isearch)
  549.   (epoch::redisplay-screen))
  550.  
  551. (defun mouse-grab-thing (arg)
  552.   "Insert grab-button at point.  Intended as an up button following
  553. mouse-select-thing as a down button."
  554.   (if (and (> mouse::clicks 0)        ; Abort grab if mouse moved.
  555.        (button-buffer grab-button))
  556.       (progn
  557.     (save-excursion
  558.       (set-buffer (button-buffer grab-button))
  559.       (setq last-command nil)
  560.       (copy-region-as-kill (button-start grab-button)
  561.                    (button-end grab-button)))
  562.     (undo-boundary)
  563.     (insert-buffer-substring (button-buffer grab-button)
  564.                  (button-start grab-button)
  565.                  (button-end grab-button))
  566.     (setq last-command nil)))
  567.   (delete-button grab-button)
  568.   (epoch::redisplay-screen))
  569.  
  570. (defun mouse-kill-thing (arg)
  571.   "Kill region highlighted by grab-button.  Intended as an up button following
  572. mouse-select-thing as a down button."
  573.   (if (and (> mouse::clicks 0)        ; Abort if mouse moved.
  574.        (button-buffer grab-button))
  575.       (save-excursion
  576.        (set-buffer (button-buffer grab-button))
  577.        (undo-boundary)
  578.        (setq last-command nil)
  579.        (delete-region (button-start grab-button)
  580.               (button-end grab-button))))
  581.   (delete-button grab-button)
  582.   (epoch::redisplay-screen))
  583.  
  584. (defun mouse-copy-thing (arg)
  585.   "Copy region highlighted by grab-button to kill ring.  Intended as
  586. an up button following mouse-select-thing as a down button."
  587.   (if (and (> mouse::clicks 0)        ; Abort if mouse moved.
  588.        (button-buffer grab-button))
  589.       (save-excursion
  590.        (set-buffer (button-buffer grab-button))
  591.        (setq last-command nil)
  592.        (copy-region-as-kill (button-start grab-button)
  593.                 (button-end grab-button))))
  594.   (delete-button grab-button)
  595.   (epoch::redisplay-screen))
  596.  
  597. (defun mouse-isearch-thing (arg)
  598.   "Start isearch with thing as default.  Type ^S to actually do the search."
  599.   (require 'thing)
  600.   (setq search-last-string
  601.     (if (and (> mouse::clicks 0)
  602.          (button-buffer grab-button))
  603.         (progn
  604.           (mouse::set-point arg)
  605.           (goto-char (button-end grab-button))
  606.           (buffer-substring (button-start grab-button) (button-end grab-button)))))
  607.   (delete-button grab-button)
  608.   (epoch::redisplay-screen)
  609.   (if (> mouse::clicks 0) (isearch t)))
  610. ;;; --------------------------------------------------------------------------
  611. ;;; Some sample bindings:
  612. ;;;
  613. ;(global-set-mouse mouse-left mouse-down 'mouse-set-spot)
  614. ;(global-set-mouse mouse-left mouse-up t)
  615. ;(global-set-mouse mouse-mode-left mouse-up 'mouse-select-buffer)
  616. ;(global-set-mouse mouse-left mouse-shift-up 'mouse-vscroll)
  617. ;; CONTROL-LEFT: isearch thing at mouse:
  618. ;(global-set-mouse mouse-left mouse-control 'mouse-select-thing)
  619. ;(global-set-mouse mouse-left mouse-control-up 'mouse-isearch-thing)
  620. ;; META-CONTROL-LEFT: grab thing at mouse:
  621. ;(global-set-mouse mouse-left mouse-meta-control 'mouse-select-thing)
  622. ;(global-set-mouse mouse-left mouse-meta-control-up 'mouse-grab-thing)
  623. ;; SHIFT-MODE-LEFT/MIDDLE/RIGHT: Make the mode line a simulated scroll bar:
  624. ;(global-set-mouse mouse-mode-left mouse-shift
  625. ;          (mousefun-set-point (scroll-up (/ (* (window-height) 
  626. ;                               (- mouse::x (car (window-edges))))
  627. ;                            (window-width)))))
  628. ;(global-set-mouse mouse-mode-middle mouse-shift
  629. ;          (mousefun-set-point (goto-char (/ (* (point-max) 
  630. ;                               (- mouse::x (car (window-edges))))
  631. ;                            (window-width)))))
  632. ;(global-set-mouse mouse-mode-right mouse-shift
  633. ;          (mousefun-set-point (scroll-down (/ (* (window-height)
  634. ;                             (- mouse::x (car (window-edges))))
  635. ;                              (window-width)))))
  636. ;; META-LEFT: find-tag at point; mode, find next tag; mini, find-tag interactively:
  637. ;(global-set-mouse mouse-left mouse-meta (mousefun-set-point (find-tag (find-tag-default))))
  638. ;(global-set-mouse mouse-mode-left mouse-meta (mousefun-set-point (tags-loop-continue nil)))
  639. ;(global-set-mouse mouse-minibuf-left mouse-meta (mousefun (call-interactively 'completing-find-tag)))
  640. ;; META-CONTROL-SHIFT-LEFT: split window vertically; mode, split vertically in half:
  641. ;(global-set-mouse mouse-left mouse-meta-control-shift 'mouse-split-window)
  642. ;(global-set-mouse mouse-mode-left mouse-meta-control-shift 'mouse-split-window)
  643. ;; META-CONTROL-SHIFT-MIDDLE: delete window:
  644. ;(global-set-mouse mouse-middle mouse-meta-control-shift (mousefun (delete-window (nth 2 arg))))
  645. ;(global-set-mouse mouse-mode-middle mouse-meta-control-shift (mousefun (delete-window (nth 2 arg))))
  646. ;; MINI-LEFT: extended command:
  647. ;(global-set-mouse mouse-minibuf-left mouse-down 'execute-extended-command)
  648.