home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / interfaces / mity-mouse / info-mouse.el < prev    next >
Encoding:
Text File  |  1993-03-28  |  10.9 KB  |  324 lines

  1. ;;!emacs
  2. ;;
  3. ;; FILE:         info-mouse.el
  4. ;; SUMMARY:      Walks through Info networks using one mouse button
  5. ;; USAGE:        GNU Emacs Lisp Library
  6. ;;
  7. ;; AUTHOR:       Bob Weiner, Applied Research, Motorola, Inc., (407)738-2087
  8. ;; E-MAIL:       USENET:  weiner@novavax.UUCP
  9. ;; ORIG-DATE:    02/04/89
  10. ;; LAST-MOD:     12/26/89
  11. ;;
  12. ;; Copyright (C) 1989 Free Software Foundation, Inc.
  13. ;;
  14. ;; This file is not yet part of GNU Emacs.
  15. ;;
  16. ;; Bob Weiner, 03/06/89
  17. ;;   Added 'mouse-non-info-command' variable to allow the 'Info-mouse' command
  18. ;;   to perform a different function when not called from within the "*info*"
  19. ;;   buffer.
  20. ;;
  21. ;;   Added 'Info-mouse-meta' command.
  22. ;;   Added 'mouse-meta-non-info-command' variable to allow the
  23. ;;   'Info-mouse-meta' command to perform a different function when not called
  24. ;;   from within the "*info*" buffer.
  25. ;;
  26. ;; Tom Horsley, 12/26/89
  27. ;;   Modified to work with my local/global mouse map stuff. It is no longer
  28. ;;   a requirement to have funny mode dependent tests, you can have a different
  29. ;;   mouse map in info mode than in other modes.
  30. ;;
  31. ;;   Also added def for last-line-p which is referenced, but not defined
  32. ;;   anywhere that I can find.
  33. ;;
  34. ;;   EMAIL: tahorsley@ssd.csd.harris.com
  35. ;;
  36. ;; DESCRIPTION:  
  37. ;;;
  38. ;;; Note this code is machine independent. (kind of) Its only requirement is
  39. ;;; that you have a pointer device and an Emacs command that sets point to
  40. ;;; the location of the pointing device's cursor.
  41. ;;;
  42. ;;; Since the changes made by Tom Horsley, it also requires separate local
  43. ;;; and global mouse maps. Since that has only been implemented for X, it
  44. ;;; has sort of gotten more device specific.
  45. ;;;
  46. ;;;
  47. ;;; To install:
  48. ;;;
  49. ;;; A pre-requsite is the mighty-mouse.el package which adds support
  50. ;;; for local and global mouse maps.
  51. ;;;
  52. ;;; All you need now is a way to setup the local map when entering info
  53. ;;; mode. This is exactly what mode hooks are for, unfortunately info mode
  54. ;;; is another one of the criminal modes that does not call a hook, so you
  55. ;;; should fix that by going into the emacs/lisp directory and adding some
  56. ;;; stuff to info.el
  57. ;;;
  58. ;;; near the top somewhere add:
  59. ;;;
  60. ;;; (defvar Info-mode-hook nil
  61. ;;;    "List of functions to run on entry to Info-mode.")
  62. ;;;
  63. ;;; then in the body for the defun Info-mode, just before exiting, add:
  64. ;;;
  65. ;;;   (run-hooks 'Info-mode-hook)
  66. ;;;
  67. ;;; This now makes info mode conform to the conventions that call for every
  68. ;;; mode to have a hook. This hook is now the place to add a setup of the
  69. ;;; local-mouse-map for info mode.
  70. ;;;
  71. ;;; From this point on, installation becomes more conventional. First add
  72. ;;; code to your .emacs file to define the variable mouse-set-point-command
  73. ;;; to be the appropriate set point command for your window system. For
  74. ;;; instance, under X you would use:
  75. ;;;
  76. ;;; (setq mouse-set-point-command 'x-mouse-info-set-point)
  77. ;;;
  78. ;;; Then set the Info-mode-hook to run the Info-mouse-setup-mode function:
  79. ;;;
  80. ;;; (setq Info-mode-hook (list 'Info-mouse-setup-mode))
  81. ;;;
  82. ;;; Then make sure emacs can find the Info-mouse-setup-mode function by adding
  83. ;;;
  84. ;;; (autoload 'Info-mouse-setup-mode "info-setup" nil t)
  85. ;;;
  86. ;;; This will automatically load the info-setup.el file containing the X
  87. ;;; specific mouse setup when info mode is first invoked.
  88. ;;;
  89. ;;;
  90. ;; DESCRIP-END.
  91.  
  92.  
  93. (provide 'info-mouse)
  94.  
  95. (defvar mouse-set-point-command nil
  96. "*Name of command that sets point to mouse cursor position.")
  97.  
  98. (defvar mouse-non-info-command 'info
  99. "*Name of command to run when button bound to 'Info-mouse' is pressed
  100. outside of the *info* buffer.  Default comand is 'info'.")
  101.  
  102. (defvar mouse-meta-non-info-command 'info
  103. "*Name of command to run when button bound to 'Info-mouse-meta' is pressed
  104. outside of the *info* buffer.  Default comand is 'info'.")
  105.  
  106. (defun Info-mouse ()
  107.   "When bound to a mouse button, allows one to move through Info
  108. documentation networks by using only that mouse button.  BE SURE TO CLEAR
  109. ANY BINDING OF THE 'UP' TRANSITION OF THE MOUSE BUTTON THAT YOU BIND
  110. THIS FUNCTION TO.
  111.  
  112. If button is clicked within:
  113.  (1) any buffer other than *info*, executes command bound to
  114.        'mouse-non-info-command' if bound;
  115.  (2) an Info Menu or Note, the desired node is found;
  116.  (3) the Up,Next,or Previous entries of a Node Header (first line),
  117.        the desired node is found;
  118.  (4) the File entry of a Node Header (first line),       
  119.        the 'Top' node within that file is found;
  120.  (5) the *info* buffer but not within a node reference and not at the
  121.      end of a node, the current node entry is scrolled up one screen
  122.  (6) the *info* buffer at the end of the current node but not within
  123.      a node reference, the Next node is found.
  124.  
  125. Returns t if button is clicked within an Info Node Header, Note
  126. (cross-reference), or a Menu; otherwise returns nil.  Returns nil if
  127. 'mouse-set-point-command' or 'mouse-non-info-command' variables are
  128. not bound to valid functions."
  129.  
  130.   (interactive)
  131.   (if (not (fboundp mouse-set-point-command))
  132.       nil
  133.     ;;
  134.     ;; Set point to cursor position
  135.     ;;
  136.     (funcall mouse-set-point-command)
  137.     ;;
  138.     ;; Test if in Info buffer already
  139.     ;;
  140.     (if (not (equal (buffer-name (current-buffer)) "*info*"))
  141.         (if (not (fboundp mouse-non-info-command))
  142.                nil
  143.             (funcall mouse-non-info-command))
  144.       (cond ((Info-handle-in-node-hdr))
  145.         ((Info-handle-in-note))
  146.         ;;
  147.         ;; If at end of node, go to next node
  148.             ;;
  149.         ((last-line-p) (Info-next))
  150.         ((Info-handle-in-menu))
  151.         ;;
  152.         ;; If nothing else scroll forward one screen.
  153.             ;;
  154.         ((scroll-up))
  155.         ))))
  156.  
  157. (defun Info-mouse-meta ()
  158.   "When bound to a meta-mouse button, allows one to move in reverse through Info
  159. documentation networks by using only that mouse button.  Used in conjunction
  160. with the 'Info-mouse' command.   BE SURE TO CLEAR ANY BINDING OF THE 'UP'
  161. TRANSITION OF THE MOUSE BUTTON THAT YOU BIND THIS FUNCTION TO.
  162.  
  163. If meta-button is clicked within:
  164.  (1) any buffer other than *info*, executes command bound to
  165.        'mouse-meta-non-info-command' if bound;
  166.  (2) an Info Menu or Note, the desired node is found;
  167.  (3) the Up,Next,or Previous entries of a Node Header (first line),
  168.        the last node in the history list is found;
  169.  (4) the File entry of a Node Header (first line),       
  170.        the 'DIR' top-level node is found;
  171.  (5) the *info* buffer but not within a node reference and not at the
  172.      end of a node, the current node entry is scrolled down one screen
  173.  (6) the *info* buffer at the end of the current node but not within
  174.      a node reference, the Previous node is found.
  175.  
  176. Returns t if button is clicked within an Info Node Header, Note
  177. (cross-reference), or a Menu; otherwise returns nil.  Returns nil if
  178. 'mouse-set-point-command' or 'mouse-meta-non-info-command' variables are
  179. not bound to valid functions."
  180.  
  181.   (interactive)
  182.   (if (not (fboundp mouse-set-point-command))
  183.       nil
  184.     ;;
  185.     ;; Set point to cursor position
  186.     ;;
  187.     (funcall mouse-set-point-command)
  188.     ;;
  189.     ;; Test if in Info buffer already
  190.     ;;
  191.     (if (not (equal (buffer-name (current-buffer)) "*info*"))
  192.         (if (not (fboundp mouse-meta-non-info-command))
  193.                nil
  194.             (funcall mouse-meta-non-info-command))
  195.       (cond ((Info-handle-in-node-hdr-meta))
  196.         ((Info-handle-in-note))
  197.         ;;
  198.         ;; If at end of node, go to previous node
  199.             ;;
  200.         ((last-line-p) (Info-prev))
  201.         ((Info-handle-in-menu))
  202.         ;;
  203.         ;; If nothing else scroll backward one screen.
  204.             ;;
  205.         ((scroll-down))
  206.         ))))
  207.  
  208. (defun Info-handle-in-node-hdr ()
  209.   "If within an Info node header, move to <FILE>Top, <Up>, <Previous>, or
  210. <Next> node, depending on which label point is on, and return t.
  211. Otherwise, return nil."
  212.   ;;
  213.   ;; Test if on 1st line of node, i.e. node header
  214.   ;;
  215.   (let* ((first-line (1+ (count-lines 1 (point-min))))
  216.      (current-line (count-lines 1 (1+ (point)))))
  217.     (if (not (equal current-line first-line))
  218.     nil
  219.       (let ((nodename "Top") (filep nil))
  220.     (save-excursion
  221.       (if (and
  222.         (re-search-forward "[:, \t\n]" nil t)
  223.         (re-search-backward
  224.           "\\(File\\|Node\\|Up\\|Prev\\|Previous\\|Next\\)[: \t]" nil t))
  225.           (progn (setq filep (string-equal
  226.                    "file"
  227.                    (downcase (buffer-substring
  228.                            (match-beginning 1)
  229.                            (match-end 1)))))
  230.              (if (re-search-forward (concat ":[ \n]\\([^,.\t\n"
  231.                             (if filep " ")
  232.                             "]*\\)") nil t)
  233.              (setq nodename (buffer-substring
  234.                       (match-beginning 1)
  235.                       (match-end 1)))))
  236.         (error "Node header not found.")))
  237.     (if filep (setq nodename (concat "(" nodename ")" "Top")))
  238.     (Info-goto-node nodename)
  239.     t))))
  240.  
  241. (defun Info-handle-in-node-hdr-meta ()
  242.   "If within an Info node header when the 'Info-mouse-meta' command is
  243. executed, when within the <FILE> header go to the DIR top-level node.  When
  244. within any other header (<Up>, <Previous>, or <Next>) go to last node from
  245. history list.  Return t if in Info node header.  Otherwise return nil."
  246.   ;;
  247.   ;; Test if on 1st line of node, i.e. node header
  248.   ;;
  249.   (let* ((first-line (1+ (count-lines 1 (point-min))))
  250.      (current-line (count-lines 1 (1+ (point)))))
  251.     (if (not (equal current-line first-line))
  252.     nil
  253.       (save-excursion
  254.     (if (and 
  255.           (re-search-forward "[:, \t\n]" nil t)
  256.           (re-search-backward
  257.         "\\(File\\|Node\\|Up\\|Prev\\|Previous\\|Next\\)[: \t]" nil t) )
  258.         ;; If in <FILE> hdr
  259.         (progn (if (string-equal
  260.              "file"
  261.              (downcase (buffer-substring
  262.                      (match-beginning 1)
  263.                      (match-end 1))))
  264.                (Info-directory)
  265.              (Info-last))
  266.            t)
  267.       (error "Node header not found.")
  268.       nil)))))
  269.  
  270. (defun Info-handle-in-note ()
  271.   "If point is within an Info note (cross-reference), follow
  272. cross-reference and return t; otherwise return nil."
  273.   ;;
  274.   ;; Test if point is within a Note
  275.   ;;
  276.   ;; Only works if entire "*Note NOTENAME" string is on one line.
  277.   ;; Follows Note if user clicks anywhere on the line.
  278.   ;;
  279.   (let ((note-name nil) (bol nil))
  280.     (save-excursion
  281.       (if (re-search-forward "[:.\n]" nil t)
  282.       (progn
  283.         (save-excursion
  284.           (beginning-of-line)
  285.           (setq bol (point)))
  286.         (if (re-search-backward "\\*Note[ \n]+\\([^:]*\\):" bol t)
  287.         (setq note-name (buffer-substring
  288.                   (match-beginning 1)
  289.                   (match-end 1)))))))
  290.     (if (not note-name)
  291.     nil
  292.       (Info-follow-reference note-name)
  293.       t)))
  294.  
  295. (defun Info-handle-in-menu ()
  296.   "If point is within an Info menu entry, go to node referenced by
  297. entry and return t; otherwise return nil."
  298.   ;;
  299.   ;; Test if there is a menu in this node
  300.   ;;
  301.   (let ((in-menu nil) (curr-point (point)))
  302.     (save-excursion
  303.       (goto-char (point-min))
  304.       (setq in-menu 
  305.         (and (re-search-forward "^\\* Menu:" nil t)
  306.          (< (point) curr-point))))
  307.     (if (not in-menu)
  308.     nil
  309.       (forward-char) ; Pass '*' char if point is in front of
  310.       (if (re-search-backward "^\\*" nil t)
  311.       (progn (forward-char 2)
  312.          (Info-goto-node (Info-extract-menu-node-name))))
  313.       t)))
  314.     
  315. ;; end info-mouse.el
  316.  
  317. (defun last-line-p ()
  318. "Return t if point is on the last line."
  319.    (save-excursion
  320.       (end-of-line 1)
  321.       (eobp)
  322.    )
  323. )
  324.