home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / interfaces / alt-mouse.el next >
Encoding:
Text File  |  1991-03-30  |  10.2 KB  |  298 lines

  1. ; Path: utkcs2!emory!swrinde!zaphod.mps.ohio-state.edu!tut.cis.ohio-state.edu!ELF.TN.CORNELL.EDU!eirik
  2. ; >From: eirik@ELF.TN.CORNELL.EDU (Eirik Fuller)
  3. ; Newsgroups: gnu.emacs
  4. ; Subject: mouse support
  5. ; Date: 24 Jul 90 03:01:04 GMT
  6. ; Organization: GNUs Not Usenet
  7. ; The enclosed lisp code provides an alternative to the X11 mouse
  8. ; support provided with GNU emacs.  Comments are welcome.  A companion
  9. ; posting will provide an example of how to use it without X11.
  10. ; This mouse support distinguishes clicks and drags.  A click is a pair
  11. ; of button events (down then up) at the same location, while a drag has
  12. ; two different locations.  A "click location" is simply the coordinates
  13. ; of a matched event pair, while a "drag region" is the text between the
  14. ; two locations in an event pair.  A distinction is also made between
  15. ; events that land on mode lines and those that don't.
  16. ; It is possible to use this mouse support outside of the X environment.
  17. ; For example, the Tektronix 4404 terminal emulator has escape sequences
  18. ; which, with the right elisp file, provide all of the necessary
  19. ; functionality for this mouse support.  For such terminals, replace
  20. ; "the X cut buffer" in what follows with "an emacs lisp variable known
  21. ; only within one emacs process".
  22. ; Here is a summary of the various bindings:
  23. ; left click:    move point to the click location
  24. ; middle click:    paste the X cut buffer at the click location
  25. ; right click:    copy the text between point and the click location
  26. ;         into the X cut buffer
  27. ; left drag:    copy the drag region to the X cut buffer
  28. ; middle drag:    paste the drag region at point
  29. ; right drag:    cut the drag region to the X cut buffer
  30. ; left & middle mode line drag:    move the mode line
  31. ; right mode line drag:        scroll the indicated window
  32. ; left mode line click:        select the indicated window
  33. ; middle mode line click:    scroll the indicated window
  34. ; right mode line click:    scroll the indicated window
  35. ; There are three bindings which scroll the indicated window, each in
  36. ; its own way.  The right mode line drag can scroll in either direction,
  37. ; depending on whether the initial or final point is on a mode line.
  38. ; The middle mode line click treats the mode line as a coordinate axis,
  39. ; with zero at the midpoint and the window height (+/-) at each end.
  40. ; The coordinate tells how far to scroll.  The right mode line click
  41. ; treats the mode line as a coordinate axis from zero to (point-max).
  42. ; The coordinate tells what part of the buffer to scroll to.
  43. ; It is possible to operate on drag regions larger than a window, if
  44. ; each end of such a region is in its own window (window in the emacs
  45. ; sense, not the X11 sense).  Drags which cross buffer boundaries do
  46. ; nothing; this provides a way to cancel a drag.
  47. ; These comments are all of the documentation for this mouse support.
  48. ; Feel free to write more; if you do, please send it (or code
  49. ; improvements, bug reports, or suggestions) to eirik@elf.tn.cornell.edu
  50.  
  51. (provide 'x-mouse)
  52. (provide 'mouse)
  53.  
  54. (fillarray mouse-map 'ignore)
  55.  
  56. (mapcar (function (lambda (s)
  57.             (define-key mouse-map s 'mouse-button-down)))
  58.     '("\000" "\001" "\002"))
  59. (define-key mouse-map "\004" 'mouse-right-up)
  60. (define-key mouse-map "\005" 'mouse-middle-up)
  61. (define-key mouse-map "\006" 'mouse-left-up)
  62.  
  63. (defvar mouse-point nil
  64.   "The mouse location during a down event.  Used by code for up events.")
  65. (defvar mouse-window nil
  66.   "The window corresponding to mouse-point.")
  67. (defvar mouse-modeline nil
  68.   "The window above the modeline pointed at by mouse-point")
  69. (defvar mouse-cut-buffer ""
  70.   "A local substitute for the X cut buffer, for terminals with mice")
  71.  
  72. (defun mouse-get-cut-buffer () 
  73.   (if (eq window-system 'x) (x-get-cut-buffer) mouse-cut-buffer))
  74.  
  75. (defun mouse-store-cut-buffer (string)
  76.   (if (eq window-system 'x) (x-store-cut-buffer string)
  77.     (setq mouse-cut-buffer string)))
  78.  
  79. (global-set-key "\C-x\C-@"
  80.         (function (lambda () 
  81.                 "Process all queued mouse events."
  82.                 (interactive)
  83.                 (while (> (x-mouse-events) 0)
  84.                   (x-proc-mouse-event)))))
  85.  
  86. (defun window-from-x-y (point)
  87.   "The window containing screen coordinates POINT."
  88.   (if (> (nth 1 point)
  89.      (- (1- (screen-height)) (window-height (minibuffer-window))))
  90.       (if (zerop (minibuffer-depth)) nil (minibuffer-window))
  91.     (let* ((start (selected-window)) (w start) (which nil))
  92.       (while (not (or (if (coordinates-in-window-p point w) (setq which w))
  93.               (eq (setq w (next-window w)) start))))
  94.       which)))
  95.  
  96. (defun mouse-button-down (point)
  97.   "Save away the window containing screen coordinates POINT"
  98.   (setq mouse-window (window-from-x-y point))
  99.   (setq mouse-point point)
  100.   (setq mouse-modeline
  101.     (if mouse-window nil
  102.         (window-from-x-y
  103.          (list (car point) (1- (nth 1 point)))))))
  104.  
  105. (defun window-below (window)
  106.   (let ((w (next-window window t)) (which nil))
  107.     (while (and (<= (nth 3 (window-edges w))
  108.             (nth 3 (window-edges window)))
  109.         (if (eq (setq w (next-window w t)) window)
  110.             (setq w nil) t)))
  111.     w))
  112.  
  113. (defun window-min-height ()
  114.   "The value of window-min-height, except for the minibuffer."
  115.   (if (eq (selected-window) (minibuffer-window)) 1 window-min-height))
  116.  
  117. (defun move-bottom (w x)
  118.   "Move the mode line beneath window W by X lines"
  119.     (let ((now (selected-window))
  120.       (below (window-below w)))
  121.       (select-window below)
  122.       (let ((y (max
  123.         (min x (- (window-height w) window-min-height))
  124.         (- (window-min-height) (window-height below)))))
  125.     (if (eq below (minibuffer-window))
  126.         (enlarge-window y)
  127.       (progn
  128.         (select-window w)
  129.         (shrink-window y))))
  130.       (select-window now)))
  131.  
  132. (defun move-side (window delta)
  133.   "Adjust vertical boundary"
  134.   (let ((w (selected-window)))
  135.     (select-window window)
  136.     (enlarge-window (if (> delta 0) delta (- 0 delta)) t)
  137.     (select-window w)))
  138.  
  139. (defun drag-modeline (point)
  140.   "If a button down found a mode line, move it on button up; else return nil"
  141.   (if mouse-modeline
  142.       (let ((y (- (nth 1 mouse-point) (nth 1 point)))
  143.         (up (list (car point) (1- (nth 1 point)))))
  144.     (if (zerop y)
  145.         (if (coordinates-in-window-p up mouse-modeline)
  146.         (select-window mouse-modeline)
  147.           (move-side mouse-modeline (- (car mouse-point) (car point))))
  148.       (move-bottom mouse-modeline y))
  149.     (setq mouse-modeline nil)
  150.     t)))
  151.  
  152. (defun move-to-x-y (point)
  153.   "Move to screen coordinates given by POINT; return resulting location"
  154.   (if point
  155.       (let ((rel (coordinates-in-window-p point (selected-window))))
  156.     (if rel (progn
  157.           (move-to-window-line (nth 1 rel))
  158.           (move-to-column (+ (car rel) (current-column)
  159.                      (max 0 (1- (window-hscroll)))))))))
  160.   (point))
  161.  
  162. (defun mouse-same-buffer-p (point)
  163.   "Use this to discard irrelevent button up events"
  164.   (let ((w (window-from-x-y point)))
  165.     (and mouse-window w
  166.      (eq (window-buffer mouse-window)
  167.          (window-buffer w)))))
  168.  
  169. (defun mouse-region (point)
  170.   "The string surrounded by two mouse events; nil if not within one buffer"
  171.   (if (mouse-same-buffer-p point)
  172.       (let ((region "") (w (selected-window)))
  173.     (select-window mouse-window)
  174.     (setq region (buffer-substring
  175.               (save-excursion
  176.             (move-to-x-y mouse-point))
  177.               (progn
  178.             (select-window (window-from-x-y point))
  179.             (save-excursion
  180.               (move-to-x-y point)))))
  181.     (select-window w)
  182.     region)))
  183.  
  184. (defun mouse-scroll-to (point abs)
  185.   "Treat the mode line as a sideways scroll bar"
  186.   (let ((w (selected-window))
  187.     (edges (window-edges mouse-modeline)))
  188.     (select-window mouse-modeline)
  189.       (unwind-protect
  190.       (if abs
  191.           (let ((x (- (nth 2 edges) (car edges))))
  192.         (goto-char (/ (* 
  193.                    (- (car point) (car edges))
  194.                    (point-max)) x))
  195.         (recenter (/ (window-height) 2)))
  196.         (let ((x (/ (+ (car edges) (nth 2 edges)) 2)))
  197.           (scroll-up (/ (* (- (car point) x)
  198.                    (window-height))
  199.                 (- x (car edges))))))
  200.     (select-window w))))
  201.  
  202. (defun mouse-insert-cut-buffer (point)
  203.   "Insert the mouse cut buffer where the mouse is pointing"
  204.   (let ((w (selected-window)))
  205.     (select-window (window-from-x-y point))
  206.     (save-excursion
  207.       (move-to-x-y point)
  208.       (insert (mouse-get-cut-buffer)))
  209.     (select-window w)))
  210.  
  211. (defun mouse-extend-selection (point)
  212.   "If in buffer of selected window, set mouse cut buffer"
  213.   (let ((w (selected-window)))
  214.     (and w mouse-window (eq (window-buffer mouse-window) (window-buffer w))
  215.      (mouse-store-cut-buffer
  216.       (let ((string
  217.          (buffer-substring
  218.           (point)
  219.           (progn (select-window mouse-window)
  220.              (save-excursion (move-to-x-y point))))))
  221.         (select-window w)
  222.         string)))))
  223.  
  224. (defun mouse-kill-region (point)
  225.   "Store region bounded by mouse events in cut buffer and delete it"
  226.   (if (mouse-same-buffer-p point)
  227.       (let ((w (selected-window)) beg end)
  228.     (select-window mouse-window)
  229.     (save-excursion
  230.       (setq beg (move-to-x-y mouse-point)))
  231.     (select-window (window-from-x-y point))
  232.     (save-excursion
  233.       (setq end (move-to-x-y point)))
  234.     (mouse-store-cut-buffer (buffer-substring beg end))
  235.     (delete-region beg end)
  236.     (select-window w)
  237.     t)))
  238.  
  239. (defun mouse-left-up (point)
  240.   "Copy dragged text to cut buffer, or position cursor, or drag mode line"
  241.   (or (drag-modeline point)
  242.       (let ((region (mouse-region point)))
  243.     (and region
  244.          (if (zerop (length region))
  245.          (progn (select-window mouse-window)
  246.             (move-to-x-y point))
  247.            (mouse-store-cut-buffer region))))))
  248.  
  249. (defun mouse-middle-up (point)
  250.   "Insert dragged text, or cut buffer, or drag mode line"
  251.   (if mouse-modeline
  252.       (if (equal point mouse-point)
  253.       (mouse-scroll-to point nil)
  254.     (drag-modeline point))
  255.     (let ((region (mouse-region point)))
  256.       (and region
  257.        (if (zerop (length region))
  258.            (mouse-insert-cut-buffer point)
  259.          (insert region))))))
  260.  
  261. (defun mouse-scroll-window (point window delta)
  262.   (and (eq window (window-from-x-y point))
  263.        (let ((w (selected-window)))
  264.      (select-window window)
  265.      (unwind-protect
  266.          (scroll-up delta))
  267.      (select-window w))))
  268.  
  269. (defun mouse-right-up (point)
  270.   "Extend the selection if no drag, or delete what's dragged"
  271.   (let ((delta (- (nth 1 mouse-point) (nth 1 point))))
  272.     (if mouse-modeline
  273.     (if (zerop delta)
  274.         (mouse-scroll-to point t)
  275.       (mouse-scroll-window point mouse-modeline delta))
  276.       (if mouse-window
  277.       (if (equal point mouse-point)
  278.           (mouse-extend-selection point)
  279.         (or (mouse-kill-region point)
  280.         (window-from-x-y point)
  281.         (mouse-scroll-window (list (car point) (1- (nth 1 point)))
  282.                    mouse-window delta)))))))
  283.  
  284.  
  285.