home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / epoch / mouse-help.el < prev    next >
Encoding:
Text File  |  1991-03-30  |  14.3 KB  |  341 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  Kenneth C. Laprade <laprade@trantor.harris-atd.com>
  22. ;;;
  23. ;;; This file is for use with Epoch, a modified version of GNU Emacs.
  24. ;;; Requires Epoch 3.2 with my patch to mouse.c.
  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. ;;; This file provides two things:
  44. ;;;    The functions describe-mouse and describe-mouse-briefly accept a mouse
  45. ;;; press and give documetation on the bindings to both the up and down
  46. ;;; events.
  47. ;;;    The function mouse-helper pops up an epoch screen with a buffer listing
  48. ;;; all the mouse bindings.  Only one set of bindings is shown at a time.
  49. ;;; Pressing the mouse on a keyword in the mode line will change the set of
  50. ;;; bindings that is displayed.
  51.  
  52.  
  53. ;;; Mouse help:
  54. (defun describe-mouse-briefly (&optional repeat)
  55.   "Print a short message about what a mouse button does.  With REPEAT,
  56. keep accepting buttons and describing them until \\[keyboard-quit]."
  57.   (interactive "P")
  58.   (describe-mouse repeat t))
  59.  
  60. (defun describe-mouse (&optional repeat brief)
  61.   "Display documentation of the function(s) a mouse button invokes.  With
  62. REPEAT (prefix interactively), keep accepting buttons and describing them
  63. until \\[keyboard-quit].  With BRIEF, just make a short message."
  64.   (interactive "P")
  65.   (push-event 'button 'mouse::help-handler)
  66.   (unwind-protect
  67.       (let ((first t))
  68.     (while (or first repeat)
  69.       (let ((mouse-press-value nil)
  70.         (mouse-press-scr nil)
  71.         (mouse-press-wait t)
  72.         (echo-keystrokes 0))
  73.         (while mouse-press-wait
  74.           (if (or first (not brief))
  75.           (message (if brief "Describe mouse button briefly:"  "Describe mouse button:")))
  76.           (sit-for 1 t)
  77.           (if (input-pending-p)
  78.           (read-char)))
  79.         (message "")
  80.         (let* ((number (nth 3 mouse-press-value))
  81.            (modstate (nth 4 mouse-press-value))
  82.            (arg (epoch::coords-to-point (nth 1 mouse-press-value) (nth 2 mouse-press-value) mouse-press-scr))
  83.            (buffer (and arg (nth 1 arg)))
  84.            ;; Find which button table (window, mode, minibuf).
  85.            (number-offset (if (and (eq mouse-press-scr (minibuf-screen))
  86.                        (= (minibuffer-depth) 0))
  87.                       mouse-minibuf
  88.                     (if (null (car arg))
  89.                     mouse-mode
  90.                       0)))
  91.            (down-index (+ mouse-down
  92.                   (if (/= 0 (logand modstate shift-mod-mask)) mouse-shift 0)
  93.                   (if (/= 0 (logand modstate control-mod-mask)) mouse-control 0)
  94.                   (if (/= 0 (logand modstate meta-mod-mask)) mouse-meta 0)
  95.                   (* mouse::button-size (+ number number-offset -1))))
  96.            (up-index (+ (- down-index mouse-down) mouse-up))
  97.            (map (and arg (symbol-buffer-value 'mouse::local-map buffer)))
  98.            (down-defn (or (and (vectorp map) (aref map down-index))
  99.                   (aref mouse::global-map down-index)))
  100.            (up-defn (or (and (vectorp map) (aref map up-index))
  101.                 (aref mouse::global-map up-index))))
  102.           (if (and (or (null down-defn) (integerp down-defn))
  103.                (or (null up-defn) (integerp up-defn)))
  104.           (message "button is undefined")
  105.         (if brief
  106.             (message "DOWN: %s  UP: %s"
  107.                  (function-description down-defn)
  108.                  (function-description up-defn))
  109.           (with-output-to-temp-buffer "*Help*"
  110.             (if down-defn (progn
  111.                     (princ "DOWN - ")
  112.                     (prin1 down-defn)
  113.                     (princ ":\n")
  114.                     (if (documentation down-defn)
  115.                     (princ (documentation down-defn))
  116.                       (princ "not documented"))
  117.                     (princ "\n\n")))
  118.             (if up-defn (progn
  119.                   (princ "UP - ")
  120.                   (prin1 up-defn)
  121.                   (princ ":\n")
  122.                   (if (documentation up-defn)
  123.                       (princ (documentation up-defn))
  124.                     (princ "not documented"))))
  125.             (print-help-return-message))
  126.           (epoch::redisplay-screen))))
  127.         (setq first nil))))
  128.     (pop-event 'button)))
  129.  
  130. (defun mouse::help-handler (type value scr)
  131.   (setq mouse-press-value value
  132.     mouse-press-scr scr
  133.     mouse-press-wait (nth 0 value)))
  134. ;;; --------------------------------------------------------------------------
  135. ;;; Mouse-helper: a popup screen describing all mouse button combinations.
  136.  
  137. (defvar mouse-helper-screen nil "Screen for mouse-helper.")
  138. (defvar auto-unmap-screens nil)        ;just in case there isn't any.
  139. (defvar last-mouse-helper-mode 1)
  140. (defvar mouse-helper-mouse-map (create-mouse-map))
  141. (define-mouse mouse-helper-mouse-map mouse-mode-left mouse-down 'mouse-helper-mode-down)
  142. (define-mouse mouse-helper-mouse-map mouse-mode-left mouse-up 'mouse-helper-mode-up)
  143. (define-mouse mouse-helper-mouse-map mouse-left mouse-down (function (lambda (arg) (mapraised-screen))))
  144. (define-mouse mouse-helper-mouse-map mouse-left mouse-up t)
  145.  
  146. (defconst mouse-helper-keys (list "WINDOW-DOWN" "WINDOW-UP"
  147.                   "MODE-DOWN" "MODE-UP"
  148.                   "MINIBUF-DOWN" "MINIBUF-UP"))
  149. (defconst mouse-helper-modes (list "WINDOW   mode   minibuf      DOWN"
  150.                    "WINDOW   mode   minibuf"
  151.                    "window   MODE   minibuf      DOWN"
  152.                    "window   MODE   minibuf"
  153.                    "window   mode   MINIBUF      DOWN"
  154.                    "window   mode   MINIBUF"))
  155. (defconst mouse-helper-offsets (list (+ mouse-down (* mouse-window mouse::button-size))
  156.                      (+ mouse-up (* mouse-window mouse::button-size))
  157.                      (+ mouse-down (* mouse-mode mouse::button-size))
  158.                      (+ mouse-up (* mouse-mode mouse::button-size))
  159.                      (+ mouse-down (* mouse-minibuf mouse::button-size))
  160.                      (+ mouse-up (* mouse-minibuf mouse::button-size))))
  161.  
  162. (defun mouse-helper-mode-down (arg)
  163.   "Show bindings for down presses."
  164.   (mouse::set-point arg)
  165.   (let ((i (cond ((< mouse::x 7) 0)
  166.          ((< mouse::x 14) 2)
  167.          (4))))
  168.     (mouse-helper-show (elt mouse-helper-keys i))
  169.     (setq mode-line-format (elt mouse-helper-modes i))
  170.     (setq last-mouse-helper-mode i)))
  171.  
  172. (defun mouse-helper-mode-up (arg)
  173.   "Show bindings for up presses.  If dragged, leave down presses showing."
  174.   (if (/= mouse::clicks 0)
  175.       (progn (mouse::set-point arg)
  176.          (let ((i (cond ((< mouse::x 7) 1)
  177.                 ((< mouse::x 14) 3)
  178.                 (5))))
  179.            (mouse-helper-show (elt mouse-helper-keys i))
  180.            (setq mode-line-format (elt mouse-helper-modes i))
  181.            (setq last-mouse-helper-mode i)))))
  182.  
  183.  
  184. (defun mouse-helper (&optional force geometry font file)
  185.   "Map or unmap the mouse helper screen.  If the screen does not exist, it
  186. is created listing the various mouse functions.  With non-nil FORCE (prefix
  187. interactively), the screen is recreated and mapped regardless of whether it
  188. already exists.  By clicking on the mode line, the contents can be changed
  189. for window, mode, or minibuf bindings.  Down bindings are shown while the
  190. button is help down.  Up bindings are shown when the button is released.
  191. If there is no up binding, the corresponding down binding is shown with a
  192. `>' prefixed.  If FORCE is 'nomap, the helper screen is left unmapped.
  193. GEOMETRY and FONT are used to create the screen.  FILE has a listing of the
  194. text for the helper buffer.  In this file, keywords `WINDOW', `MODE', and
  195. 'MINIBUF' with suffixes `UP' and `DOWN' indicate the different sections.
  196. The associated section is enclosed by blank lines following the keyword.
  197. Without FILE, the helper text is built from the current global mouse
  198. bindings."
  199.   (interactive "P")
  200.   (if (and (screenp mouse-helper-screen)
  201.        (get-screen-id mouse-helper-screen))
  202.       (progn
  203.     (if (or (not (get-buffer " *mouse-helper*"))
  204.         (not (memq mouse-helper-screen (screens-of-buffer " *mouse-helper*"))))
  205.         (setq force (or force t)))
  206.     (if (or (eq force 'nomap)
  207.         (and (not force) (memq mouse-helper-screen (screen-list))))
  208.         (progn (unmap-screen mouse-helper-screen)
  209.            (setq auto-unmap-screens (delq 'mouse-helper-screen auto-unmap-screens)))
  210.       (mapraised-screen mouse-helper-screen)
  211.       (or (memq 'mouse-helper-screen auto-unmap-screens)
  212.           (setq auto-unmap-screens (append auto-unmap-screens (list 'mouse-helper-screen)))))))
  213.   (if (or force
  214.       (not (screenp mouse-helper-screen))
  215.       (not (get-screen-id mouse-helper-screen)))
  216.       (save-excursion
  217.     (set-buffer (get-buffer-create " *mouse-helper*"))
  218.     (erase-buffer)
  219.     (if (and (stringp file) (file-exists-p file))
  220.         (insert-file-contents file)
  221.       (let ((keys mouse-helper-keys)
  222.         (offsets mouse-helper-offsets)
  223.         (width (if geometry (string-to-int geometry) 100)))
  224.         (while keys
  225.           (insert "\n\n" (car keys) "\n\n")
  226.           (build-mouse-help mouse::global-map (car offsets) width)
  227.           (setq keys (cdr keys)
  228.             offsets (cdr offsets)))))
  229.     (mouse-helper-show (elt mouse-helper-keys last-mouse-helper-mode))
  230.     (setq mode-line-format (elt mouse-helper-modes last-mouse-helper-mode))
  231.     (use-local-mouse-map mouse-helper-mouse-map)))
  232.   (if (and (screenp mouse-helper-screen)
  233.        (get-screen-id mouse-helper-screen))
  234.       (set-window-buffer (epoch::selected-window mouse-helper-screen)
  235.              " *mouse-helper*")
  236.     (setq mouse-helper-screen
  237.       (create-screen " *mouse-helper*"
  238.              (screen-attributes (or geometry "100x9+250+-26") "MOUSE"
  239.                         (cons 'font (or font "5x8")))))
  240.     (if (eq force 'nomap)
  241.     (progn (unmap-screen mouse-helper-screen)
  242.            (setq auto-unmap-screens (delq 'mouse-helper-screen auto-unmap-screens)))
  243.       (or (memq 'mouse-helper-screen auto-unmap-screens)
  244.       (setq auto-unmap-screens (append auto-unmap-screens (list 'mouse-helper-screen)))))))
  245.  
  246. (defvar uninteresting-fncs (list 'mouse::set-point 'mouse-set-point
  247.                  'start-mouse-drag 'call-interactively
  248.                  'quote 'save-excursion 'set-buffer
  249.                  'nth  'undo-boundary 'setq))
  250.  
  251. (defun interesting-function (l)
  252.   "Return the first function mentioned in the list that is not in
  253. uninteresting-fncs."
  254.   (let ((f nil))
  255.     (while (and l (listp l)
  256.         (if (functionp f)
  257.             (memq f uninteresting-fncs)
  258.           t))
  259.       (setq f (car l))
  260.       (if (and f (listp f))
  261.       (setq f (interesting-function f)))
  262.       (setq l (cdr l)))
  263.     f))
  264.  
  265. (defun function-description (func &optional max)
  266.   "Return a string describing the function FUNC.  If it is a lambda list,
  267. any documentation string is used.  If there is no documentation string, the
  268. first function in the list that is not in uninteresting-fncs is used.
  269. With optional MAX, limits string to MAX characters."
  270.   (if (null func)
  271.       ""
  272.     (let ((s (if (functionp func)
  273.          (documentation func))))
  274.       (if (and (listp func)
  275.            (eq (car func) 'lambda))
  276.       (or s
  277.           (setq func (interesting-function func)))
  278.     (setq s nil))
  279.       (or s (setq s (format "%s" func)))
  280.       (substring s 0 (if max (min (length s) max))))))
  281.  
  282. (defconst mouse-helper-states-text (list "PLAIN" "CONTROL" "SHIFT" "META"
  283.                        "C-S" "M-C" "M-S" "M-C-S"))
  284. (defconst mouse-helper-states (list mouse-down mouse-control mouse-shift mouse-meta
  285.                       mouse-control-shift mouse-meta-control
  286.                       mouse-meta-shift mouse-meta-control-shift))
  287.  
  288. (defun build-mouse-help (map offset width)
  289.   "Build the mouse-helper text from bindings in MAP at OFFSET.  For any
  290. buttons with no binding on one edge, the other edge's entry is used (with a
  291. `>' prefixed).  WIDTH is the number of columns each line should fit in."
  292.   (let ((states mouse-helper-states)
  293.     (states-text mouse-helper-states-text)
  294.     entry)
  295.     (setq width (/ (- width 10) 3))
  296.     (while states
  297.       (insert (car states-text))
  298.       (indent-to 8 1)
  299.       (if (setq entry (aref map (+ (car states) (* mouse-left mouse::button-size) offset)))
  300.       (insert (function-description entry width))
  301.     (if (setq entry (aref map (logxor
  302.                    (+ (car states) (* mouse-left mouse::button-size) offset)
  303.                    mouse-up)))
  304.         (insert ?> (function-description entry (1- width)))))
  305.       (indent-to (+ 9 width) 1)
  306.       (if (setq entry (aref map (+ (car states) (* mouse-middle mouse::button-size) offset)))
  307.       (insert (function-description entry width))
  308.     (if (setq entry (aref map (logxor
  309.                    (+ (car states) (* mouse-middle mouse::button-size) offset)
  310.                    mouse-up)))
  311.         (insert ?> (function-description entry (1- width)))))
  312.       (indent-to (+ 10 width width) 1)
  313.       (if (setq entry (aref map (+ (car states) (* mouse-right mouse::button-size) offset)))
  314.       (insert (function-description entry width))
  315.     (if (setq entry (aref map (logxor
  316.                    (+ (car states) (* mouse-right mouse::button-size) offset)
  317.                    mouse-up)))
  318.         (insert ?>(function-description entry (1- width)))))
  319.       (insert ?\n)
  320.       (setq states (cdr states)
  321.         states-text (cdr states-text)))))
  322.  
  323. (defun mouse-helper-show (keyword)
  324.   "Narrow the mouse-helper buffer to text associated with regexp KEYWORD.
  325. Assumes mouse-helper buffer is selected."
  326.   (widen)
  327.   (goto-char (point-min))
  328.   (re-search-forward keyword)
  329.   (let ((beg (if (search-forward "\n\n" nil t)
  330.          (match-end 0) (point))))
  331.     (search-forward "\n\n" nil 'end)
  332.     (while (eq (preceding-char) ?\n)
  333.       (backward-char))
  334.     (narrow-to-region beg (point)))
  335.   (goto-char (point-min)))
  336.