home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / browser2.zip / br-brows.el < prev    next >
Text File  |  1995-02-17  |  22KB  |  600 lines

  1. ;;; CLASS BROWSER FOR C++
  2. ;;; $Id: br-brows.el,v 3.1 1995/02/17 18:19:36 mmann Exp $
  3. ;;;
  4. ;;; **********************************************************************
  5. ;;; Copyright (C) 1993, 1994 Gerd Moellmann. All rights reserved.
  6. ;;; Altenbergstr. 6, D-40235 Duesseldorf, Germany
  7. ;;; 100025.3303@COMPUSERVE.COM
  8. ;;; Suggestions, comments and requests for improvements are welcome.
  9. ;;; **********************************************************************
  10. ;;;
  11. ;;; This version works with both Emacs version 18 and 19, and I want
  12. ;;; to keep it that way (at least as long as Emacs Lisp is dynamic :-)
  13. ;;; It requires the CL-19 Common Lisp compatibility package for Emacs 18
  14. ;;; and 19.
  15. ;;;
  16. ;;; This file contains the stub that is always loaded when you
  17. ;;; `(require 'br-browse)'.  It installs a FIND-FILE hook
  18. ;;; that loads a tree structure into memory.  It also contains utility
  19. ;;; functions used in various parts of the package.
  20. ;;;
  21. ;;; NAMING CONVENTIONS:
  22. ;;;
  23. ;;; * all buffer-local variables in this package start with `@'.
  24. ;;; * this package uses the prefixes `tree-', `browse-', `member-', and
  25. ;;;   `class-'.
  26. ;;; 
  27.  
  28. ;; IDEAS FOR IMPLEMENTATION:
  29. ;; * Prepare for name spaces. 
  30. ;; * Edit member attributes like `virtual', `const' etc., edit regular
  31. ;;   expressions.
  32. ;; * When members are deleted/added add them to member obarray. Likewise
  33. ;;   for classes.
  34. ;; * In member buffers provide a `SuperGoto' which positions on any
  35. ;;   member defined in the tree.
  36. ;; * If 2 members with the same name exist in the same class and regexps
  37. ;;   are known for one member but not for the other, the function
  38. ;;   BROWSE-TAGS-READ-NAME will return just one member. It shpuld pop
  39. ;;   up a list of those members applicable, in a way so that the members
  40. ;;   are distinguishable.
  41. ;; * Make new functions available via menu.
  42. ;; * Write documentation.
  43.  
  44. ;; NEWS
  45. ;; * find-file, write-file, save-buffer, revert-buffer and so on
  46. ;;   can now be used on trees. The function `browse' is gone.
  47. ;; * Classes in the tree can be marked for later operations.
  48. ;; * browse-search, browse-query-replace, browse-loop are work-alikes
  49. ;;   for their `tags-' counterparts with the following differences:
  50. ;;   (a) if classes are marked in the tree, only files from the marked
  51. ;;   classes are visited, and (b) files that aren't modified and
  52. ;;   weren't visited when the operation starts are discarded.
  53. ;; * Classes and members can be deleted, regions and buffers can be
  54. ;;   added to the tree. The tree can be saved.
  55. ;; * Regular expressions can optionally be placed in a separate file
  56. ;;   that is only loaded when needed.
  57. ;; * Files generated with ebrowse option `-n' (no regexps) are handled
  58. ;;   better, so that you can use `-n' most of the time.
  59. ;; * Global functions, variables, types are now part of the tree.
  60. ;; * Electric position stack display.
  61. ;; * Positioning will load file if not present in a buffer
  62. ;; * Code cleanup
  63. ;; * Symbol completion for members in the tree.
  64. ;; * Much faster operation of `browse-tags-find'.
  65. ;; * Electric tree buffer selection for operations on trees.
  66. ;; * Superclass lists built incrementally to improve load time and
  67. ;;   reduces memory consumption.
  68. ;; * list-tags and -apropos.
  69. ;; * Search for member usage.
  70.  
  71. ;; This file may be made part of the Emacs distribution at the option
  72. ;; of the FSF.
  73.  
  74. ;; This code is distributed in the hope that it will be useful,
  75. ;; but WITHOUT ANY WARRANTY.  No author or distributor
  76. ;; accepts responsibility to anyone for the consequences of using it
  77. ;; or for whether it serves any particular purpose or works at all,
  78. ;; unless he says so in writing.  Refer to the GNU Emacs General Public
  79. ;; License for full details.
  80.  
  81. ;; Everyone is granted permission to copy, modify and redistribute
  82. ;; this code, but only under the conditions described in the
  83. ;; GNU Emacs General Public License.   A copy of this license is
  84. ;; supposed to have been given to you along with GNU Emacs so you
  85. ;; can know your rights and responsibilities.  It should be in a
  86. ;; file named COPYING.  Among other things, the copyright notice
  87. ;; and this notice must be preserved on all copies.
  88.  
  89. (require 'backquote)                    ;to make life easier
  90. (require 'cl-19 "cl")
  91.  
  92.  
  93. ;;;
  94. ;;;
  95. ;;;
  96.  
  97. ;; (if (> (string-to-int emacs-version) 18)
  98. ;;     (progn
  99. ;;       (require 'cl-19 "cl")
  100. ;;       (eval-when-compile
  101. ;;         (progn
  102. ;;           (require 'cl-compat)
  103. ;;           (require 'view)
  104. ;;           (load "cl-extra")
  105. ;;           (load "cl-macs"))))
  106. ;;   (require 'cl))
  107.  
  108. (require 'br-struc)
  109. (require 'br-macro)
  110. (require 'br-rev)
  111.  
  112. ;;;
  113. ;;; Autoloads.
  114. ;;; 
  115.  
  116. (autoload 'tree-files-obarray "br-loop")
  117. (autoload 'browse-next-file "br-loop" nil t)
  118. (autoload 'browse-tags-find-member-buffer "br-tags" nil t)
  119. (autoload 'member-goto "br-membe")
  120. (autoload 'browse-electric-choose-tree "br-trees")
  121. (autoload 'tree-choose-buffer "br-trees")
  122. (autoload 'browse-find-tree "br-tags")
  123. (autoload 'tree-marked-exist-p "br-tree")
  124. (autoload 'browse-tags-read-name "br-tags")
  125. (autoload 'tree-choose-buffer "br-trees")
  126. (autoload 'browse-complete-symbol "br-compl" 
  127.       "Complete the symbol point is on." t)
  128. (autoload 'browse-add-buffer "br-add"
  129.       "Parse buffer and add result to tree." t)
  130. (autoload 'browse-add-region "br-add"
  131.       "Parse region and add result to tree." t)
  132. (autoload 'browse-tags-back "br-posit" 
  133.       "Move backward in position stack." t)
  134. (autoload 'browse-tags-forward "br-posit"
  135.       "Move forward in position stack." t)
  136. (autoload 'browse-electric-position-list "br-posit"
  137.       "Display position stack in electric buffer." t)
  138. (autoload 'browse-tags-find "br-tags" "Find member point is on." t)
  139. (autoload 'browse-tags-view "br-tags" "View member point is on." t)
  140. (autoload 'browse-tags-apropos "br-tags"
  141.       "View list of members matching regular expression." t)
  142. (autoload 'browse-tags-list "br-tags" "List members in a file." t)
  143. (autoload 'browse-loop "br-loop" "Continue last tags operation." t)
  144. (autoload 'browse-search "br-loop" "Search for regexp in tree files." t)
  145. (autoload 'browse-search-member-usage "br-loop" 
  146.       "Search for call of given member." t)
  147. (autoload 'browse-query-replace "br-loop"
  148.       "Perform query replace over files in tree." t)
  149. (autoload 'tree-save "br-save" "Save tree to disk." t)
  150. (autoload 'tree-write "br-save" "Write tree to different file." t)
  151. (autoload 'tree-statistics "br-stat" "Display tree statistics." t)
  152. (autoload 'tree-write-regexps "br-save" "Write regular expressions to file." t)
  153. (autoload 'member-display "br-membe")
  154. (autoload 'tree-choose-buffer "br-trees")
  155. (autoload 'browse-tags-push-position "br-posit")
  156. (autoload 'browse-electric-choose-tree "br-trees")
  157. (autoload 'tree-create-buffer "br-tree")
  158. (autoload 'browse-tags-member-search "br-tags")
  159.  
  160.  
  161. (defvar browse-options '(verbose)
  162.   "A list of symbols each one describing an interesting aspect of the
  163. system on which the browser is installed, or an option specified by
  164. users. The following symbols can be included:
  165.  
  166. verbose         option; be verbose when loading files
  167. emacs-19        system; if we are running under Emacs 19.")
  168.  
  169. ;;;
  170. ;;; If we are running under Emacs 19, include the symbol 'emacs-19 in
  171. ;;; BROWSE-OPTIONS.
  172. ;;; 
  173.  
  174. (when (> (string-to-int emacs-version) 18)
  175.   (push 'emacs-19 browse-options))
  176.  
  177. ;;;
  178. ;;; Increase size of stack.
  179. ;;; 
  180.  
  181. (eval-when (compile)
  182.   (setq max-lisp-eval-depth (max 300 max-lisp-eval-depth)))
  183.  
  184.  
  185. ;;; A string stored in the BROWSE file specifiying the Lisp package
  186. ;;; version required.
  187. (defconst browse-version-string "GeM 3.00")
  188.  
  189. ;;; The name used for the `global' class. This must be the same that
  190. ;;; `ebrowse' uses.
  191. (defconst browse-global-tree-name "*Globals*")
  192.  
  193. ;;; Last regular expression searched for in tree and member buffers.
  194. ;;; Automatically buffer local so that each tree and member buffer
  195. ;;; maitains its own search history.
  196. (make-variable-buffer-local 'browse-last-regexp)
  197. (defvar browse-last-regexp nil)
  198.  
  199. (defvar browse-find-hook nil
  200.   "Hooks run after finding or viewing a definition or declaration.")
  201.  
  202. (defvar browse-not-found-hook nil
  203.   "Hooks run when finding or viewing was not successfull.")
  204.   
  205. (defvar browse-window-configuration nil
  206.   "Window configuration saved/restored in Emacs 18.")
  207.  
  208. (defvar browse-enable-menu-bar t
  209.   "*T means show menu bar in Emacs 19.")
  210.  
  211. (defvar browse-fast-member-lookup t
  212.   "T means build obarray of members to speed up member lookup.  This
  213. cost additional memory, so it could be necessary to switch this option
  214. off if working on large trees.")
  215.  
  216. (defvar browse-lazy-fast-members t
  217.   "T means that the obarray of all members is only built when it is
  218. needed the first time. This feature is for speeding up loading.")
  219.  
  220. (defvar browse-hilit-on-redisplay t
  221.   "T means rehighlight buffer if redisplayed.")
  222.  
  223. (defvar member-lists '(tree-member-variables
  224.                        tree-member-functions
  225.                        tree-static-variables
  226.                        tree-static-functions
  227.                        tree-friends
  228.                        tree-types)
  229.   "A list of symbols each of which is an accessor for a member list
  230. displayed in the browser.")
  231.  
  232. (defconst member-buffer-name "*Members*"
  233.   "*The name of the temporary buffer for member display.")
  234.  
  235. ;;;
  236. ;;; Completion with ignored case in Emacs 18 doesn't
  237. ;;; convert the minibuffer contents to the right case when
  238. ;;; the minibuffer is already a complete match (case insensitive).
  239. ;;; When this happens, VALUE will be nil.
  240. ;;;
  241. ;;; This function performs a completion with an ALIST and returns
  242. ;;; the VALUE part of the completion read.
  243. ;;;
  244.  
  245. (defun browse-completing-read-value (title alist initial)
  246.   (browse-completion-ignoring-case
  247.     (let ((key (completing-read title alist nil t initial)))
  248.       (or (cdr (assoc key alist))
  249.       (loop for x in alist
  250.         with downcase-key = (downcase key)
  251.         until (string= (downcase (car x)) downcase-key)
  252.         finally return (cdr x))))))
  253.  
  254. ;;;
  255. ;;; Return the value of the buffer-local variable SYM in BUFFER.
  256. ;;; Note that we cannot simply search for an association in the
  257. ;;; list of buffer-local variables since not all variables are kept
  258. ;;; in form of an association.
  259. ;;; 
  260.  
  261. (defun* browse-@value
  262.     (sym buffer &aux (old-buffer (current-buffer)))
  263.   (unwind-protect
  264.       (progn (set-buffer buffer) (symbol-value sym))
  265.     (set-buffer old-buffer)))
  266.  
  267. ;;;
  268. ;;; Return an ALIST of elements (CLASS-NAME . TREE) for all classes
  269. ;;; in the tree stored in the buffer-local variable @TREE-OBARRAY.
  270. ;;; Note that this function must be called in a buffer containing
  271. ;;; such a local variable.
  272. ;;; 
  273.  
  274. (defun* tree-alist (&aux alist)
  275.   (dotrees (tree @tree-obarray)
  276.     (setq alist (acons (class-name (tree-class tree)) tree alist)))
  277.   alist)
  278.  
  279. ;;;
  280. ;;; Sort a list of TREE structures alphabetically.
  281. ;;;
  282.  
  283. (defun browse-sort-tree-list (list)
  284.   (sort list (function
  285.           (lambda (a b) (string< (class-name (tree-class a))
  286.                      (class-name (tree-class b)))))))
  287.  
  288. ;;;
  289. ;;; Rename current buffer to NEW-NAME.  If a buffer with
  290. ;;; name NEW-NAME already exists, delete it first.
  291. ;;; 
  292.  
  293. (defun* browse-rename-buffer-safe
  294.     (new-name &aux (old-buffer (get-buffer new-name)))
  295.   (unless (eq old-buffer (current-buffer))
  296.     (when old-buffer
  297.       (save-excursion (kill-buffer old-buffer)))
  298.     (rename-buffer new-name)))
  299.  
  300. ;;;
  301. ;;; Return a copy of STRING with leading white space removed,
  302. ;;; and with newlines in it replaced with a single space.
  303. ;;;
  304.  
  305. (defun browse-trim (string)
  306.   (when (string-match "^[ \t\n\r]+" string)
  307.     (setf string (substring string (match-end 0))))
  308.   (loop while (string-match "[\n]+" string)
  309.     finally return string do
  310.     (setf string (concat (substring string 0 (match-beginning 0)) " "
  311.                  (substring string (match-end 0))))))
  312.  
  313. ;;;
  314. ;;; Install a FIND-FILE hook that when finding a BROWSE structure file
  315. ;;; creates a new tree buffer. Note that ADD-HOOK in the Gillespie
  316. ;;; CL package has to be fixed to work properly.
  317. ;;; 
  318.  
  319. (defun browse-find-tree-hook ()
  320.   (when (looking-at "\\[cl-struct-tree-header")
  321.     (browse-load-file buffer-file-name 'switch)))
  322.  
  323. (add-hook 'find-file-hooks 'browse-find-tree-hook)
  324.  
  325. ;;;
  326. ;;; Search for a class with the same name as CLASS in TREE.
  327. ;;; Return the class found, if any. This function is used during the
  328. ;;; load phase where classes appended to a file replace older class
  329. ;;; information.
  330. ;;; 
  331.  
  332. (defun* browse-find-root (class tree)
  333.   (find class tree
  334.         :test (function (lambda (class root)
  335.                           (string= (class-name (tree-class root))
  336.                                    (class-name (tree-class class)))))))
  337.  
  338. ;;;
  339. ;;; Give some feedback for lengthy operations.
  340. ;;; 
  341.  
  342. (defvar browse-progress-counter -1)
  343. (defvar browse-progress-msgs '("--" "\\" "|" "/"))
  344.  
  345. (defun browse-indicate-progress (title &optional start)
  346.   (when start (setq browse-progress-counter -1))
  347.   (message (concat title " "
  348.            (nth (logand 3 (incf browse-progress-counter))
  349.             browse-progress-msgs)
  350.            "  ")))
  351.  
  352. ;;;
  353. ;;; Read TREE-HEADER and TREE structures the current buffer. 
  354. ;;; Return as multiple values (HEADER TREE) where HEADER is the header
  355. ;;; read an TREE is a list of TREE structures making up the class
  356. ;;; tree.
  357. ;;; 
  358.  
  359. (defun browse-read-class-list ()
  360.   (when (progn (goto-char 1) (eobp))
  361.     (error "File is empty."))
  362.  
  363.   (let ((header (read (current-buffer)))
  364.         tree)
  365.     ;; Check version
  366.     (unless (and (tree-header-p header)
  367.                  (string= (tree-header-version header)
  368.                           browse-version-string))
  369.       (error "File has wrong version number %s (%s expected)!"
  370.              (tree-header-version header)
  371.              browse-version-string))
  372.  
  373.     ;; Convert path of regexp file to absolute form.
  374.     (unless (or (null (tree-header-regexp-file header))
  375.                 (file-name-absolute-p (tree-header-regexp-file header)))
  376.       (setf (tree-header-regexp-file header)
  377.             (expand-file-name (tree-header-regexp-file header))))
  378.  
  379.     ;; Read Lisp objects. Temporarily increase GC-CONS-THRESHOLD to
  380.     ;; a large value to prevent garbage collections that would not
  381.     ;; free any memory.
  382.  
  383.     (let ((old-threshold gc-cons-threshold))
  384.       (unwind-protect
  385.       (progn
  386.         (setf gc-cons-threshold 1000000)
  387.  
  388.         ;; Read Lisp objects
  389.         (while (not (eobp))
  390.           (let* ((root (read (current-buffer)))
  391.              (old-root (browse-find-root root tree)))
  392.         (browse-indicate-progress "Reading data" (null tree))
  393.         (if old-root
  394.             (setf (car old-root) root)
  395.           (push root tree))
  396.         (skip-chars-forward " \t\n"))))
  397.  
  398.     (setf gc-cons-threshold old-threshold)))
  399.  
  400.     (garbage-collect)
  401.     (values header tree)))
  402.  
  403. ;;;
  404. ;;; Load a browser file into memory.  This function is normally called
  405. ;;; via a FIND-FILE hook.
  406. ;;; 
  407.  
  408. (defun browse-load-file (file &optional switch)
  409.   (let (tree
  410.         header
  411.         (buffer (get-file-buffer file))
  412.         tree-buffer)
  413.     (if buffer
  414.         (multiple-value-setq (header tree) (browse-read-class-list))
  415.       (save-excursion
  416.         ;; Since find-file hooks may be involved, we must visit the
  417.         ;; file in a way that these hooks are not called.
  418.         (set-buffer (create-file-buffer file))
  419.         (erase-buffer)
  420.         (insert-file file)
  421.         (set-buffer-modified-p nil)
  422.         (unwind-protect
  423.             (multiple-value-setq (header tree) (browse-read-class-list))
  424.           (kill-buffer (current-buffer)))))
  425.  
  426.     (when tree
  427.       (message "Sorting. Please be patient...")
  428.       (setf tree (browse-sort-tree-list tree))
  429.  
  430.       ;; Create tree buffer
  431.       (setf tree-buffer (tree-create-buffer tree
  432.                                             file
  433.                                             header
  434.                                             (browse-build-tree-obarray tree)
  435.                                             switch
  436.                                             buffer))
  437.  
  438.       (message "")
  439.       tree-buffer)))
  440.  
  441. ;;;
  442. ;;; This function must be called with current buffer in tree mode.
  443. ;;; It constructs an obarray with a symbol for each member of all classes
  444. ;;; mentioned in the buffer-local OBARRAY @TREE-OBARRAY. Each symbol
  445. ;;; has its property 'INFO set to a list of (TREE MEMBER-LIST MEMBER) lists
  446. ;;; where TREE is the tree in which the member is defined in, MEMBER-LIST
  447. ;;; is a symbol describing the member list in which the member is found,
  448. ;;; and MEMBER is a MEMBER structure describing the member. The slot
  449. ;;; MEMBER-OBARRAY of the buffer-local structure TREE-HEADER is set to
  450. ;;; this obarray.
  451. ;;; 
  452.  
  453. (defun tree-fill-member-obarray ()
  454.   (let ((members (make-vector 127 0))
  455.     (i -1))
  456.  
  457.     (setf (tree-header-member-obarray @header) nil)
  458.     (garbage-collect)
  459.  
  460.     ;; For all classes...
  461.     (dotrees (c @tree-obarray)
  462.       (when (zerop (% (incf i) 10))
  463.     (browse-indicate-progress "Preparing member lookup" (zerop i)))
  464.  
  465.       (loop for f in member-lists do
  466.             (loop for m in (funcall f c) do
  467.                   (let ((sym (intern (member-name m) members)))
  468.                     (push (list c f m) (get sym 'info))))))
  469.  
  470.     ;; Set slot MEMBER-OBARRAY of local variable @HEADER.
  471.     (setf (tree-header-member-obarray @header) members)))
  472.  
  473. ;;;
  474. ;;; Make sure every TREE in the class tree is represented by a
  475. ;;; unique object. Build obarray of all classes in tree.
  476. ;;; 
  477.  
  478. (defun* browse-build-tree-obarray (tree
  479.                     &aux (classes (make-vector 127 0)))
  480.   ;; Add root classes...
  481.   (loop for root in tree
  482.         as sym = (intern (class-name (tree-class root)) classes) do
  483.         (unless (get sym 'browse-root)
  484.           (setf (get sym 'browse-root) root)))
  485.  
  486.   ;; Process subclasses
  487.   (br$insert-supers tree classes)
  488.   classes)
  489.  
  490. ;;;
  491. ;;; Helper function for BROWSE-BUILD-TREE-OBARRAY
  492. ;;; Superclasses should be ordered so that the immediate base
  493. ;;; comes first, then the base class of the immediate base class
  494. ;;; and so on.  This means that we must construct the superclass
  495. ;;; list top down with adding each level at the beginning of the
  496. ;;; superclass list.
  497. ;;;
  498. ;;; We have to be cautious here not to end up in an infinite
  499. ;;; recursion if for some reason a circle is in the inheritance
  500. ;;; graph.
  501. ;;; 
  502.  
  503. (defun br$insert-supers (tree classes)
  504.   (loop for class in tree
  505.     as subclasses = (tree-subclasses class) do
  506.  
  507.     ;; Make sure every class is represented by a unique object
  508.     (loop for subclass on subclasses
  509.           as sym = (intern (class-name (tree-class (car subclass)))
  510.                    classes)
  511.           as next = nil
  512.           do
  513.  
  514.           ;; Replace the subclass tree with the one found in
  515.           ;; CLASSES if there is already an entry for that class
  516.           ;; in it. Otherwise make a new entry.
  517.           ;;
  518.           ;; CAVEAT: If by some means (e.g., use of the
  519.           ;; preprocessor in class declarations, a name is marked
  520.           ;; as a subclass of itself on some path, we would end up
  521.           ;; in an endless loop. We have to omit subclasses from
  522.           ;; the recursion that already have been processed.
  523.  
  524.           (if (get sym 'browse-root)
  525.           (setf (car subclass) (get sym 'browse-root))
  526.         (setf (get sym 'browse-root) (car subclass))))
  527.           
  528.     ;; Process subclasses
  529.     (br$insert-supers subclasses classes)))
  530.  
  531. ;;;
  532. ;;; Kill all member buffers displaying TREE.
  533. ;;; 
  534.  
  535. (defun browse-kill-member-buffers-displaying (tree)
  536.   (loop for b in (member-buffers)
  537.     as c = (browse-@value '@displayed-class b)
  538.     when (eq c tree) do (kill-buffer b)))
  539.  
  540. ;;;
  541. ;;; Remove a class from a tree. Kill all member buffers still containing
  542. ;;; a reference to the TREE.
  543. ;;; 
  544.  
  545. (defun browse-remove-class (tree class)
  546.   (let ((sym (intern-soft (class-name (tree-class class)) @tree-obarray)))
  547.     (setf tree (delq class tree)
  548.           (get sym 'browse-root) nil)
  549.     (dolist (root tree)
  550.       (setf (tree-subclasses root) (delq class (tree-subclasses root))
  551.             (tree-superclasses root) nil)
  552.       (browse-remove-class (tree-subclasses root) class))
  553.     (browse-kill-member-buffers-displaying class)
  554.     tree))
  555.  
  556. ;;;
  557. ;;; Build the member obarray.
  558. ;;; 
  559.  
  560. (defun browse-member-obarray (header)
  561.   (when (and (null (tree-header-member-obarray header))
  562.          browse-fast-member-lookup)
  563.     (loop for buffer in (browse-buffers)
  564.       until (eq header
  565.             (browse-@value '@header buffer))
  566.       finally do (save-excursion
  567.                (set-buffer buffer)
  568.                (tree-fill-member-obarray))))
  569.   (tree-header-member-obarray header))
  570.       
  571. ;;;
  572. ;;; Mouse support.
  573. ;;;
  574. ;;; The following function can be used to position point on the
  575. ;;; definition of a member under the mouse cursor.
  576. ;;; 
  577. ;;; There is some problem with double clicks here.  If we change the
  578. ;;; window in the following function, the event will set the point
  579. ;;; in the new window. We would need to have a function that kills the
  580. ;;; event.
  581. ;;; ###FIXME Can use function brows-read-class-and-member.
  582. ;;; 
  583.  
  584. (defun browse-mouse-member-find (event)
  585.   (interactive "e")
  586.   (mouse-set-point event)
  587.   (let (start name)
  588.     (save-excursion
  589.       (skip-chars-backward "a-zA-Z0-9_")
  590.       (setq start (point))
  591.       (skip-chars-forward "a-zA-Z0-9_")
  592.       (setq name (buffer-substring start (point))))
  593.     (browse-tags-member-search nil t name)))
  594.  
  595. (provide 'browse)
  596.  
  597. ;;; end of `browse.el'.
  598.     
  599.  
  600.