]> code.delx.au - gnu-emacs/blobdiff - lisp/find-file.el
(calc-embedded-make-info): Use `math-read-expr' when
[gnu-emacs] / lisp / find-file.el
index d6a6d7c419926f2bd623830d46e103b1011bae4f..e15d6e62b0b078fe5b554a65f262b4db71fc746c 100644 (file)
@@ -1,9 +1,11 @@
 ;;; find-file.el --- find a file corresponding to this one given a pattern
 
-;; Author:         Henry Guillaume <henry@qbd.com.au>
+;; Author: Henry Guillaume <henri@tibco.com, henry@c032.aone.net.au>
+;; Maintainer: FSF
 ;; Keywords: c, matching, tools
 
-;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 1995, 2002, 2003, 2004,
+;;   2005, 2006 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
 ;; PURPOSE:
-;; This package features a function called ff-find-other-file, which performs 
-;; the following function: 
+;; This package features a function called ff-find-other-file, which performs
+;; the following function:
 ;;
 ;;     When in a .c file, find the first corresponding .h file in a set
 ;;     of directories and display it, and vice-versa from the .h file.
@@ -37,7 +39,7 @@
 ;; to find that file.
 ;;
 ;; THE "OTHER FILE", or "corresponding file", generally has the same basename,
-;; and just has a different extension as described by the ff-other-file-alist 
+;; and just has a different extension as described by the ff-other-file-alist
 ;; variable:
 ;;
 ;;   '(("\\.cc$"  (".hh" ".h"))
 ;; format above can be changed to include a function to be called when the
 ;; current file matches the regexp:
 ;;
-;;   '(("\\.cc$"  cc-function)
+;;   '(("\\.cc$"  cc--function)
 ;;     ("\\.hh$"  hh-function))
 ;;
-;; These functions must return a list consisting of the possible names of the 
-;; corresponding file, with or without path. There is no real need for more 
+;; These functions must return a list consisting of the possible names of the
+;; corresponding file, with or without path. There is no real need for more
 ;; than one function, and one could imagine the following value for cc-other-
 ;; file-alist:
 ;;
@@ -69,9 +71,9 @@
 ;;          ("\\.hh$"  ff-cc-hh-converter)
 ;;          ("\\.c$"   (".h"))
 ;;          ("\\.h$"   (".c" ".cc" ".C" ".CC" ".cxx" ".cpp"))))
-;; 
+;;
 ;; ff-cc-hh-converter is included at the end of this file as a reference.
-;; 
+;;
 ;; SEARCHING is carried out in a set of directories specified by the
 ;; ff-search-directories variable:
 ;;
 ;;
 ;; If the file was not found, ff-find-other-file will prompt you for where
 ;; to create the new "corresponding file" (defaults to the current directory),
-;; unless the variable ff-always-try-to-create is set to nil. 
+;; unless the variable ff-always-try-to-create is set to nil.
 ;;
-;; GIVEN AN ARGUMENT (with the ^U prefix), ff-find-other-file will get the 
-;; other file in another (the other?) window (see find-file-other-window and 
-;; switch-to-buffer-other-window). This can be set on a more permanent basis 
-;; by setting ff-always-in-other-window to t in which case the ^U prefix will 
+;; GIVEN AN ARGUMENT (with the ^U prefix), ff-find-other-file will get the
+;; other file in another (the other?) window (see find-file-other-window and
+;; switch-to-buffer-other-window). This can be set on a more permanent basis
+;; by setting ff-always-in-other-window to t in which case the ^U prefix will
 ;; do the opposite of what was described above.
 ;;
 ;; THERE ARE FIVE AVAILABLE HOOKS, called in this order if non-nil:
 ;;
-;; - ff-pre-find-hooks     - called before the search for the other file starts
-;; - ff-not-found-hooks    - called when the other file could not be found
-;; - ff-pre-load-hooks     - called just before the other file is 'loaded'
-;; - ff-file-created-hooks - called when the other file is created
-;; - ff-post-load-hooks    - called just after the other file is 'loaded'
+;; - ff-pre-find-hook     - called before the search for the other file starts
+;; - ff-not-found-hook    - called when the other file could not be found
+;; - ff-pre-load-hook     - called just before the other file is 'loaded'
+;; - ff-file-created-hook - called when the other file is created
+;; - ff-post-load-hook    - called just after the other file is 'loaded'
 ;;
-;; The *load-hooks allow you to place point where you want it in the other
-;; file. 
-
-;;; Change Log:
-;;
-;; FEEDBACK:
-;; Please send me bug reports, bug fixes, and extensions, so that I can
-;; merge them into the master source.
+;; The *load-hook allow you to place point where you want it in the other
+;; file.
 
 ;; CREDITS:
 ;; Many thanks go to TUSC Computer Systems Pty Ltd for providing an environ-
 ;; Many thanks also go to all those who provided valuable feedback throughout
 ;; the development of this package:
 ;;     Rolf Ebert in particular, Fritz Knabe, Heddy Boubaker, Sebastian Kremer,
-;;     Vasco Lopes Paulo, Mark A. Plaksin, Robert Lang, Trevor West, Kevin 
+;;     Vasco Lopes Paulo, Mark A. Plaksin, Robert Lang, Trevor West, Kevin
 ;;     Pereira, Benedict Lofstedt & Justin Vallon.
 
 ;;; Code:
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; User definable variables:
 
-(defvar ff-pre-find-hooks nil
-  "*List of functions to be called before the search for the file starts.")
-
-(defvar ff-pre-load-hooks nil
-  "*List of functions to be called before the other file is loaded.")
-
-(defvar ff-post-load-hooks nil
-  "*List of functions to be called after the other file is loaded.")
-
-(defvar ff-not-found-hooks nil
-  "*List of functions to be called if the other file could not be found.")
-
-(defvar ff-file-created-hooks nil
-  "*List of functions to be called if the other file needs to be created.")
-
-(defvar ff-case-fold-search nil
+(defgroup ff nil
+  "Find a file corresponding to this one given a pattern."
+  :prefix "ff-"
+  :link '(emacs-commentary-link "find-file")
+  :group 'find-file)
+
+(defcustom ff-pre-find-hook nil
+  "*List of functions to be called before the search for the file starts."
+  :type 'hook
+  :group 'ff)
+
+(defcustom ff-pre-load-hook nil
+  "*List of functions to be called before the other file is loaded."
+  :type 'hook
+  :group 'ff)
+
+(defcustom ff-post-load-hook nil
+  "*List of functions to be called after the other file is loaded."
+  :type 'hook
+  :group 'ff)
+
+(defcustom ff-not-found-hook nil
+  "*List of functions to be called if the other file could not be found."
+  :type 'hook
+  :group 'ff)
+
+(defcustom ff-file-created-hook nil
+  "*List of functions to be called if the other file needs to be created."
+  :type 'hook
+  :group 'ff)
+
+(defcustom ff-case-fold-search nil
   "*Non-nil means ignore cases in matches (see `case-fold-search').
-If you have extensions in different cases, you will want this to be nil.")
+If you have extensions in different cases, you will want this to be nil."
+  :type 'boolean
+  :group 'ff)
 
-(defvar ff-always-in-other-window nil
+(defcustom ff-always-in-other-window nil
   "*If non-nil, find the corresponding file in another window by default.
-To override this, give an argument to `ff-find-other-file'.")
+To override this, give an argument to `ff-find-other-file'."
+  :type 'boolean
+  :group 'ff)
 
-(defvar ff-ignore-include nil
-  "*If non-nil, ignore `#include' lines.")
+(defcustom ff-ignore-include nil
+  "*If non-nil, ignore `#include' lines."
+  :type 'boolean
+  :group 'ff)
 
-(defvar ff-always-try-to-create t
-  "*If non-nil, always attempt to create the other file if it was not found.")
+(defcustom ff-always-try-to-create t
+  "*If non-nil, always attempt to create the other file if it was not found."
+  :type 'boolean
+  :group 'ff)
 
-(defvar ff-quiet-mode nil
-  "*If non-nil, trace which directories are being searched.")
+(defcustom ff-quiet-mode nil
+  "*If non-nil, trace which directories are being searched."
+  :type 'boolean
+  :group 'ff)
 
-(defvar ff-special-constructs 
+;;;###autoload
+(defvar ff-special-constructs
   '(
     ;; C/C++ include, for NeXTSTEP too
     ("^\#\\s *\\(include\\|import\\)\\s +[<\"]\\(.*\\)[>\"]" .
      (lambda ()
        (setq fname (buffer-substring (match-beginning 2) (match-end 2)))))
-
-    ;; Ada import
-    ("^with[ \t]+\\([a-zA-Z0-9_\\.]+\\)" .
-     (lambda ()
-       (setq fname (buffer-substring (match-beginning 1) (match-end 1)))
-       (require 'ada-mode)
-       (setq fname (concat (ada-make-filename-from-adaname fname)
-                          ada-spec-suffix))))
     )
-  "*A list of regular expressions specifying how to recognise special 
-constructs such as include files etc, and an associated method for 
-extracting the filename from that construct.")
+  "*A list of regular expressions for `ff-find-file'.
+Specifies how to recognize special constructs such as include files
+etc. and an associated method for extracting the filename from that
+construct.")
 
-(defvar ff-other-file-alist 'cc-other-file-alist
+(defvaralias 'ff-related-file-alist 'ff-other-file-alist)
+(defcustom ff-other-file-alist 'cc-other-file-alist
   "*Alist of extensions to find given the current file's extension.
 
 This list should contain the most used extensions before the others,
 since the search algorithm searches sequentially through each
 directory specified in `ff-search-directories'.  If a file is not found,
 a new one is created with the first matching extension (`.cc' yields `.hh').
-This alist should be set by the major mode.")
+This alist should be set by the major mode."
+  :type '(choice (repeat (list regexp (choice (repeat string) function)))
+                symbol)
+  :group 'ff)
 
-(defvar ff-search-directories 'cc-search-directories
+(defcustom ff-search-directories 'cc-search-directories
   "*List of directories to search for a specific file.
 
 Set by default to `cc-search-directories', expanded at run-time.
 
 This list is searched through with each extension specified in
 `ff-other-file-alist' that matches this file's extension.  So the
-longer the list, the longer it'll take to realise that a file
+longer the list, the longer it'll take to realize that a file
 may not exist.
 
-A typical format is 
+A typical format is
 
     '(\".\" \"/usr/include\" \"$PROJECT/*/include\")
 
@@ -209,52 +229,65 @@ not exist, it is replaced (silently) with an empty string.
 
 The stars are *not* wildcards: they are searched for together with
 the preceding slash.  The star represents all the subdirectories except
-`..', and each of these subdirectories will be searched in turn.")
+`..', and each of these subdirectories will be searched in turn."
+  :type '(choice (repeat directory) symbol)
+  :group 'ff)
 
-(defvar cc-search-directories
+(defcustom cc-search-directories
   '("." "/usr/include" "/usr/local/include/*")
-  "*See the description of the `ff-search-directories' variable.")
+  "*See the description of the `ff-search-directories' variable."
+  :type '(repeat directory)
+  :group 'ff)
 
-(defvar cc-other-file-alist
-  '(
-    ("\\.cc$"  (".hh" ".h"))
-    ("\\.hh$"  (".cc" ".C"))
+(defcustom cc-other-file-alist
+  '(("\\.cc\\'"  (".hh" ".h"))
+    ("\\.hh\\'"  (".cc" ".C"))
 
-    ("\\.c$"   (".h"))
-    ("\\.h$"   (".c" ".cc" ".C" ".CC" ".cxx" ".cpp"))
+    ("\\.c\\'"   (".h"))
+    ("\\.h\\'"   (".c" ".cc" ".C" ".CC" ".cxx" ".cpp"))
 
-    ("\\.C$"   (".H"  ".hh" ".h"))
-    ("\\.H$"   (".C"  ".CC"))
+    ("\\.C\\'"   (".H"  ".hh" ".h"))
+    ("\\.H\\'"   (".C"  ".CC"))
 
-    ("\\.CC$"  (".HH" ".H"  ".hh" ".h"))
-    ("\\.HH$"  (".CC"))
+    ("\\.CC\\'"  (".HH" ".H"  ".hh" ".h"))
+    ("\\.HH\\'"  (".CC"))
 
-    ("\\.cxx$" (".hh" ".h"))
-    ("\\.cpp$" (".hh" ".h"))
-    )
+    ("\\.c\\+\\+\\'" (".h++" ".hh" ".h"))
+    ("\\.h\\+\\+\\'" (".c++"))
+
+    ("\\.cpp\\'" (".hpp" ".hh" ".h"))
+    ("\\.hpp\\'" (".cpp"))
+
+    ("\\.cxx\\'" (".hxx" ".hh" ".h"))
+    ("\\.hxx\\'" (".cxx")))
   "*Alist of extensions to find given the current file's extension.
 
 This list should contain the most used extensions before the others,
 since the search algorithm searches sequentially through each directory
 specified in `ff-search-directories'.  If a file is not found, a new one
-is created with the first matching extension (`.cc' yields `.hh').")
+is created with the first matching extension (`.cc' yields `.hh')."
+  :type '(repeat (list regexp (choice (repeat string) function)))
+  :group 'ff)
 
-(defvar modula2-other-file-alist
+(defcustom modula2-other-file-alist
   '(
     ("\\.mi$" (".md")) ;; Modula-2 module definition
     ("\\.md$" (".mi")) ;; and implementation.
     )
-  "*See the description for the `ff-search-directories' variable.")
+  "*See the description for the `ff-search-directories' variable."
+  :type '(repeat (list regexp (choice (repeat string) function)))
+  :group 'ff)
+
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; No user definable variables beyond this point!
 ;; ==============================================
 
-(make-variable-buffer-local 'ff-pre-find-hooks)
-(make-variable-buffer-local 'ff-pre-load-hooks)
-(make-variable-buffer-local 'ff-post-load-hooks)
-(make-variable-buffer-local 'ff-not-found-hooks)
-(make-variable-buffer-local 'ff-file-created-hooks)
+(make-variable-buffer-local 'ff-pre-find-hook)
+(make-variable-buffer-local 'ff-pre-load-hook)
+(make-variable-buffer-local 'ff-post-load-hook)
+(make-variable-buffer-local 'ff-not-found-hook)
+(make-variable-buffer-local 'ff-file-created-hook)
 (make-variable-buffer-local 'ff-case-fold-search)
 (make-variable-buffer-local 'ff-always-in-other-window)
 (make-variable-buffer-local 'ff-ignore-include)
@@ -268,7 +301,7 @@ is created with the first matching extension (`.cc' yields `.hh').")
 ;;;###autoload
 (defun ff-get-other-file (&optional in-other-window)
   "Find the header or source file corresponding to this file.
-See also the documentation for `ff-find-other-file;.
+See also the documentation for `ff-find-other-file'.
 
 If optional IN-OTHER-WINDOW is non-nil, find the file in another window."
   (interactive "P")
@@ -277,6 +310,9 @@ If optional IN-OTHER-WINDOW is non-nil, find the file in another window."
     (ff-find-the-other-file in-other-window)
     (setq ff-ignore-include ignore)))
 
+;;;###autoload
+(defalias 'ff-find-related-file 'ff-find-other-file)
+
 ;;;###autoload
 (defun ff-find-other-file (&optional in-other-window ignore-include)
   "Find the header or source file corresponding to this file.
@@ -287,48 +323,48 @@ If optional IGNORE-INCLUDE is non-nil, ignore being on `#include' lines.
 
 Variables of interest include:
 
- - ff-case-fold-search
-   Non-nil means ignore cases in matches (see case-fold-search).
+ - `ff-case-fold-search'
+   Non-nil means ignore cases in matches (see `case-fold-search').
    If you have extensions in different cases, you will want this to be nil.
 
- - ff-always-in-other-window 
+ - `ff-always-in-other-window'
    If non-nil, always open the other file in another window, unless an
-   argument is given to ff-find-other-file.
+   argument is given to `ff-find-other-file'.
 
- - ff-ignore-include 
+ - `ff-ignore-include'
    If non-nil, ignores #include lines.
 
- - ff-always-try-to-create 
+ - `ff-always-try-to-create'
    If non-nil, always attempt to create the other file if it was not found.
 
- - ff-quiet-mode 
+ - `ff-quiet-mode'
    If non-nil, traces which directories are being searched.
 
- - ff-special-constructs 
-   A list of regular expressions specifying how to recognise special 
-   constructs such as include files etc, and an associated method for 
+ - `ff-special-constructs'
+   A list of regular expressions specifying how to recognize special
+   constructs such as include files etc, and an associated method for
    extracting the filename from that construct.
 
- - ff-other-file-alist
+ - `ff-other-file-alist'
    Alist of extensions to find given the current file's extension.
 
- - ff-search-directories 
+ - `ff-search-directories'
    List of directories searched through with each extension specified in
-   ff-other-file-alist that matches this file's extension.
+   `ff-other-file-alist' that matches this file's extension.
 
- - ff-pre-find-hooks 
+ - `ff-pre-find-hook'
    List of functions to be called before the search for the file starts.
 
- - ff-pre-load-hooks 
+ - `ff-pre-load-hook'
    List of functions to be called before the other file is loaded.
 
- - ff-post-load-hooks
+ - `ff-post-load-hook'
    List of functions to be called after the other file is loaded.
 
- - ff-not-found-hooks
+ - `ff-not-found-hook'
    List of functions to be called if the other file could not be found.
 
- - ff-file-created-hooks
+ - `ff-file-created-hook'
    List of functions to be called if the other file has been created."
   (interactive "P")
   (let ((ignore ff-ignore-include))
@@ -339,13 +375,6 @@ Variables of interest include:
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Support functions
 
-(defun ff-emacs-19 ()
-  (string-match "^19\\.[0-9]+\\.[0-9]+$" emacs-version))
-
-(defun ff-xemacs ()
-  (or (string-match "Lucid"  emacs-version)
-      (string-match "XEmacs" emacs-version)))
-
 (defun ff-find-the-other-file (&optional in-other-window)
   "Find the header or source file corresponding to the current file.
 Being on a `#include' line pulls in that file, but see the help on
@@ -362,13 +391,12 @@ If optional IN-OTHER-WINDOW is non-nil, find the file in another window."
         alist           ;; working copy of the list of file extensions
         pathname        ;; the pathname of the file or the #include line
         default-name    ;; file we should create if none found
-        format          ;; what we have to match    
-        found           ;; name of the file or buffer found - nil if none 
+        format          ;; what we have to match
+        found           ;; name of the file or buffer found - nil if none
         dirs            ;; local value of ff-search-directories
         no-match)       ;; whether we know about this kind of file
 
-    (if ff-pre-find-hooks
-        (run-hooks 'ff-pre-find-hooks))
+    (run-hooks 'ff-pre-find-hook 'ff-pre-find-hooks)
 
     (message "Working...")
 
@@ -395,8 +423,7 @@ If optional IN-OTHER-WINDOW is non-nil, find the file in another window."
                          (buffer-file-name)
                        "/none.none"))
 
-      (string-match ".*/\\(.+\\)$" pathname)
-      (setq fname (substring pathname (match-beginning 1) (match-end 1))
+      (setq fname (file-name-nondirectory pathname)
             no-match nil
             match (car alist))
 
@@ -416,7 +443,7 @@ If optional IN-OTHER-WINDOW is non-nil, find the file in another window."
               action (car (cdr match))
               found nil)
 
-        ;; if we have a function to generate new names, 
+        ;; if we have a function to generate new names,
         ;; invoke it with the name of the current file
         (if (and (atom action) (fboundp action))
             (progn
@@ -426,7 +453,7 @@ If optional IN-OTHER-WINDOW is non-nil, find the file in another window."
                     default-name (car suffixes)))
 
           ;; otherwise build our filename stub
-          (cond 
+          (cond
 
            ;; get around the problem that 0 and nil both mean false!
            ((= pos 0)
@@ -445,25 +472,24 @@ If optional IN-OTHER-WINDOW is non-nil, find the file in another window."
                 (concat stub (car (car (cdr match))))))
 
         ;; do the real work - find the file
-        (setq found 
+        (setq found
               (ff-get-file dirs
                            stub
-                           suffixes 
+                           suffixes
                            in-other-window)))))
 
     (cond
      (no-match                     ;; could not even determine the other file
       (message ""))
 
-     (t 
+     (t
       (cond
 
        ((not found)                ;; could not find the other file
 
-        (if ff-not-found-hooks     ;; run the hooks
-            (run-hooks 'ff-not-found-hooks))
+       (run-hooks 'ff-not-found-hook 'ff-not-found-hooks)
 
-        (cond 
+        (cond
          (ff-always-try-to-create  ;; try to create the file
           (let (name pathname)
 
@@ -472,12 +498,12 @@ If optional IN-OTHER-WINDOW is non-nil, find the file in another window."
                    (read-file-name
                     (format "Find or create %s in: " default-name)
                     default-directory default-name nil)))
-            
+
             (setq pathname
                   (if (file-directory-p name)
                       (concat (file-name-as-directory name) default-name)
                     (setq found name)))
-            
+
             (ff-find-file pathname in-other-window t)))
 
          (t                        ;; don't create the file, just whinge
@@ -488,24 +514,118 @@ If optional IN-OTHER-WINDOW is non-nil, find the file in another window."
 
     found))                        ;; return buffer-name or filename
 
-(defun ff-get-file (search-dirs fname-stub &optional suffix-list other-window)
-  "Find a file in the SEARCH-DIRS with the given FILENAME (or filename stub). 
-If (optional) SUFFIXES is nil, search for fname, otherwise search for fname 
-with each of the given suffixes. Gets the file or the buffer corresponding 
-to the name of the first file found, or nil.
-
-Arguments: (search-dirs fname-stub &optional suffix-list in-other-window)
-"
-  (let ((filename (ff-get-file-name search-dirs fname-stub suffix-list)))
-            
-    (cond 
+(defun ff-other-file-name ()
+  "Return name of the header or source file corresponding to the current file.
+Being on a `#include' line pulls in that file, but see the help on
+the `ff-ignore-include' variable."
+
+  (let (match           ;; matching regexp for this file
+        suffixes        ;; set of replacing regexps for the matching regexp
+        action          ;; function to generate the names of the other files
+        fname           ;; basename of this file
+        pos             ;; where we start matching filenames
+        stub            ;; name of the file without extension
+        alist           ;; working copy of the list of file extensions
+        pathname        ;; the pathname of the file or the #include line
+        default-name    ;; file we should create if none found
+        format          ;; what we have to match
+        found           ;; name of the file or buffer found - nil if none
+        dirs            ;; local value of ff-search-directories
+        no-match)       ;; whether we know about this kind of file
+
+    (message "Working...")
+
+    (setq dirs
+          (if (symbolp ff-search-directories)
+              (ff-list-replace-env-vars (symbol-value ff-search-directories))
+            (ff-list-replace-env-vars ff-search-directories)))
+
+    (save-excursion
+      (beginning-of-line 1)
+      (setq fname (ff-treat-as-special)))
+
+    (cond
+     ((and (not ff-ignore-include) fname)
+      (setq default-name fname)
+      (setq found (ff-get-file-name dirs fname nil)))
+
+     ;; let's just get the corresponding file
+     (t
+      (setq alist (if (symbolp ff-other-file-alist)
+                      (symbol-value ff-other-file-alist)
+                    ff-other-file-alist)
+            pathname (if (buffer-file-name)
+                         (buffer-file-name)
+                       "/none.none"))
+
+      (setq fname (file-name-nondirectory pathname)
+            no-match nil
+            match (car alist))
+
+      ;; find the table entry corresponding to this file
+      (setq pos (ff-string-match (car match) fname))
+      (while (and match (if (and pos (>= pos 0)) nil (not pos)))
+        (setq alist (cdr alist))
+        (setq match (car alist))
+        (setq pos (ff-string-match (car match) fname)))
+
+      ;; no point going on if we haven't found anything
+      (if (not match)
+          (setq no-match t)
+
+        ;; otherwise, suffixes contains what we need
+        (setq suffixes (car (cdr match))
+              action (car (cdr match))
+              found nil)
+
+        ;; if we have a function to generate new names,
+        ;; invoke it with the name of the current file
+        (if (and (atom action) (fboundp action))
+            (progn
+              (setq suffixes (funcall action (buffer-file-name))
+                    match (cons (car match) (list suffixes))
+                    stub nil
+                    default-name (car suffixes)))
+
+          ;; otherwise build our filename stub
+          (cond
+
+           ;; get around the problem that 0 and nil both mean false!
+           ((= pos 0)
+            (setq format "")
+            (setq stub "")
+            )
+
+           (t
+            (setq format (concat "\\(.+\\)" (car match)))
+            (string-match format fname)
+            (setq stub (substring fname (match-beginning 1) (match-end 1)))
+            ))
+
+          ;; if we find nothing, we should try to get a file like this one
+          (setq default-name
+                (concat stub (car (car (cdr match))))))
+
+        ;; do the real work - find the file
+        (setq found
+              (ff-get-file-name dirs stub suffixes)))))
+    found))                        ;; return buffer-name or filename
+
+(defun ff-get-file (search-dirs filename &optional suffix-list other-window)
+  "Find a file in the SEARCH-DIRS with the given FILENAME (or filename stub).
+If (optional) SUFFIX-LIST is nil, search for fname, otherwise search
+for fname with each of the given suffixes.  Get the file or the buffer
+corresponding to the name of the first file found, or nil."
+  (let ((filename (ff-get-file-name search-dirs filename suffix-list)))
+
+    (cond
      ((not filename)
       nil)
 
      ((bufferp (get-file-buffer filename))
       (ff-switch-to-buffer (get-file-buffer filename) other-window)
       filename)
-               
+
      ((file-exists-p filename)
       (ff-find-file filename other-window nil)
       filename)
@@ -514,12 +634,10 @@ Arguments: (search-dirs fname-stub &optional suffix-list in-other-window)
       nil))))
 
 (defun ff-get-file-name (search-dirs fname-stub &optional suffix-list)
-  "Find a file in the SEARCH-DIRS with the given FILENAME (or filename stub). 
-If (optional) SUFFIXES is nil, search for fname, otherwise search for fname 
-with each of the given suffixes. Returns the name of the first file found.
-
-Arguments: (search-dirs fname-stub &optional suffix-list)
-"
+  "Find a file in SEARCH-DIRS with the given name (or stub) FNAME-STUB.
+If (optional) SUFFIX-LIST is nil, search for FNAME-STUB, otherwise
+search for FNAME-STUB with each of the given suffixes.  Return the
+name of the first file found."
   (let* (dirs         ;; working copy of dirs to search
          dir          ;; the current dir considered
          file         ;; filename being looked for
@@ -539,7 +657,7 @@ Arguments: (search-dirs fname-stub &optional suffix-list)
         (setq this-suffix (car suffixes))
       (setq this-suffix "")
       (setq suffixes (list "")))
-            
+
     ;; find whether the file is in a buffer first
     (while (and suffixes (not found))
       (setq filename (concat fname-stub this-suffix))
@@ -572,26 +690,26 @@ Arguments: (search-dirs fname-stub &optional suffix-list)
 
       ;; if dir does not contain '/*', look for the file
       (if (and dir (not (string-match "\\([^*]*\\)/\\\*\\(/.*\\)*" dir)))
-          (progn 
-            
+          (progn
+
             ;; suffixes is nil => fname-stub is the file we are looking for
             ;; otherwise fname-stub is a stub, and we append a suffix
             (if suffixes
                 (setq this-suffix (car suffixes))
               (setq this-suffix "")
               (setq suffixes (list "")))
-            
+
             (while (and suffixes (not found))
 
               (setq filename (concat fname-stub this-suffix))
               (setq file (concat dir "/" filename))
-              
+
               (if (not ff-quiet-mode)
                   (message "Finding %s..." file))
 
               (if (file-exists-p file)
                   (setq found file))
-              
+
               (setq suffixes (cdr suffixes))
               (setq this-suffix (car suffixes))))
 
@@ -652,7 +770,7 @@ The value used comes from `ff-case-fold-search'."
     (setq search-list (reverse list))))
 
 (defun ff-treat-as-special ()
-  "Returns the file to look for if the construct was special, else nil.
+  "Return the file to look for if the construct was special, else nil.
 The construct is defined in the variable `ff-special-constructs'."
   (let* (fname
          (list ff-special-constructs)
@@ -669,7 +787,7 @@ The construct is defined in the variable `ff-special-constructs'."
     fname))
 
 (defun ff-basename (string)
-  "Return the basename of PATHNAME."
+  "Return the basename of pathname STRING."
   (setq string (concat "/" string))
   (string-match ".*/\\([^/]+\\)$" string)
   (setq string (substring string (match-beginning 1) (match-end 1))))
@@ -705,89 +823,52 @@ and on the global variable `ff-always-in-other-window'.
 F1 and F2 are typically `find-file' / `find-file-other-window'
 or `switch-to-buffer' / `switch-to-buffer-other-window' function pairs.
 
-If optional NEW-FILE is t, then a special hook (`ff-file-created-hooks') is 
-called before `ff-post-load-hooks'."
-  (if ff-pre-load-hooks
-      (run-hooks 'ff-pre-load-hooks))
+If optional NEW-FILE is t, then a special hook (`ff-file-created-hook') is
+called before `ff-post-load-hook'."
+  (run-hooks 'ff-pre-load-hook 'ff-pre-load-hooks)
   (if (or
        (and in-other-window (not ff-always-in-other-window))
        (and (not in-other-window) ff-always-in-other-window))
       (funcall f2 file)
     (funcall f1 file))
   (if new-file
-      (if ff-file-created-hooks
-          (run-hooks 'ff-file-created-hooks)))
-  (if ff-post-load-hooks
-      (run-hooks 'ff-post-load-hooks)))
+      (run-hooks 'ff-file-created-hook 'ff-file-created-hooks))
+  (run-hooks 'ff-post-load-hook 'ff-post-load-hooks))
 
 (defun ff-find-file (file &optional in-other-window new-file)
   "Like `find-file', but may show the file in another window."
-  (ff-switch-file 'find-file 
-                  'find-file-other-window 
+  (ff-switch-file 'find-file
+                  'find-file-other-window
                   file in-other-window new-file))
 
 (defun ff-switch-to-buffer (buffer-or-name &optional in-other-window)
   "Like `switch-to-buffer', but may show the buffer in another window."
 
-  (ff-switch-file 'switch-to-buffer 
-                  'switch-to-buffer-other-window 
+  (ff-switch-file 'switch-to-buffer
+                  'switch-to-buffer-other-window
                   buffer-or-name in-other-window nil))
 
-(cond 
- ((ff-emacs-19)
-  (defun ff-goto-click (event)
-    (set-buffer (window-buffer (posn-window (event-end event))))
-    (goto-char (posn-point (event-end event))))
-
-  ;;;###autoload
-  (defun ff-mouse-find-other-file (event)
-    "Visit the file you click on."
-    (interactive "e")
-    (save-excursion
-      (ff-goto-click event)
-      (ff-find-other-file nil)))
-
-  ;;;###autoload
-  (defun ff-mouse-find-other-file-other-window (event)
-    "Visit the file you click on."
-    (interactive "e")
-    (save-excursion
-      (ff-goto-click event)
-      (ff-find-other-file t)))
-
-  ;;;###autoload
-  (defun locate-file (fname dirs &optional suffix-list ignore-perms)
-    "Defines XEmacs look-alike locate-file for GNU Emacs-19."
-    (interactive)
-    (ff-get-file dirs fname suffix-list)) 
-  )
-
- ((ff-xemacs)
-
-  ;;;###autoload
-  (defun ff-mouse-find-other-file (event)
-    "Visit the file you click on."
-    (interactive "@e")
-    (save-excursion
-      (mouse-set-point event)
-      (ff-find-other-file nil)))
-
-  ;;;###autoload
-  (defun ff-mouse-find-other-file-other-window (event)
-    "Visit the file you click on."
-    (interactive "@e")
-    (save-excursion
-      (mouse-set-point event)
-      (ff-find-other-file t))) 
-  ))
+;;;###autoload
+(defun ff-mouse-find-other-file (event)
+  "Visit the file you click on."
+  (interactive "e")
+  (save-excursion
+    (mouse-set-point event)
+    (ff-find-other-file nil)))
 
-(provide 'find-file)
+;;;###autoload
+(defun ff-mouse-find-other-file-other-window (event)
+  "Visit the file you click on in another window."
+  (interactive "e")
+  (save-excursion
+    (mouse-set-point event)
+    (ff-find-other-file t)))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; This section offers an example of user defined function to select files
 
 (defun ff-upcase-p (string &optional start end)
-  "Return t if this string is all uppercase.
+  "Return t if STRING is all uppercase.
 Given START and/or END, checks between these characters."
   (let (match str)
     (if (not start)
@@ -797,7 +878,7 @@ Given START and/or END, checks between these characters."
     (if (= start end)
         (setq end (1+ end)))
     (setq str (substring string start end))
-    (if (and 
+    (if (and
          (ff-string-match "[A-Z]+" str)
          (setq match (match-data))
          (= (car match) 0)
@@ -810,18 +891,18 @@ Given START and/or END, checks between these characters."
 Build up a new file list based possibly on part of the directory name
 and the name of the file passed in."
   (ff-string-match "\\(.*\\)/\\([^/]+\\)/\\([^.]+\\).\\([^/]+\\)$" arg)
-  (let ((path (if (match-beginning 1) 
+  (let ((path (if (match-beginning 1)
                   (substring arg (match-beginning 1) (match-end 1)) nil))
-        (dire (if (match-beginning 2) 
+        (dire (if (match-beginning 2)
                   (substring arg (match-beginning 2) (match-end 2)) nil))
-        (file (if (match-beginning 3) 
+        (file (if (match-beginning 3)
                   (substring arg (match-beginning 3) (match-end 3)) nil))
-        (extn (if (match-beginning 4) 
+        (extn (if (match-beginning 4)
                   (substring arg (match-beginning 4) (match-end 4)) nil))
         return-list)
     (cond
      ;; fooZapJunk.cc => ZapJunk.{hh,h} or fooZapJunk.{hh,h}
-     ((and (string= extn "cc") 
+     ((and (string= extn "cc")
            (ff-string-match "^\\([a-z]+\\)\\([A-Z].+\\)$" file))
       (let ((stub  (substring file (match-beginning 2) (match-end 2))))
         (setq dire (upcase (substring file (match-beginning 1) (match-end 1))))
@@ -833,7 +914,7 @@ and the name of the file passed in."
      ;; FOO/ZapJunk.hh => fooZapJunk.{cc,C} or ZapJunk.{cc,C}
      ((and (string= extn "hh") (ff-upcase-p dire) file)
       (let ((stub (concat (downcase dire) file)))
-        (setq return-list (list (concat stub ".cc")           
+        (setq return-list (list (concat stub ".cc")
                                 (concat stub ".C")
                                 (concat file ".cc")
                                 (concat file ".C")))
@@ -850,9 +931,9 @@ and the name of the file passed in."
         (setq return-list (list (concat stub ".cc")
                                 (concat stub ".C")))
         ))
-     (t 
+     (t
       nil))
-    
+
     return-list))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -861,27 +942,21 @@ and the name of the file passed in."
 
 (defvar ff-function-name nil "Name of the function we are in.")
 
-(eval-when-compile (require 'ada-mode))
-
-;; bind with (setq ff-pre-load-hooks 'ff-which-function-are-we-in)
+;; bind with (setq ff-pre-load-hook 'ff-which-function-are-we-in)
 ;;
+(defvar ada-procedure-start-regexp)
+(defvar ada-package-start-regexp)
+
 (defun ff-which-function-are-we-in ()
   "Return the name of the function whose definition/declaration point is in.
 Also remember that name in `ff-function-name'."
+  (setq ff-function-name
+        (save-excursion
+          (if (or (re-search-backward ada-procedure-start-regexp nil t)
+                  (re-search-backward ada-package-start-regexp nil t))
+              (match-string 0)))))
 
-  (setq ff-function-name nil)
-
-  (save-excursion
-    (if (re-search-backward ada-procedure-start-regexp nil t)
-        (setq ff-function-name (buffer-substring (match-beginning 0)
-                                                 (match-end 0)))
-      ; we didn't find a procedure start, perhaps there is a package
-      (if (re-search-backward ada-package-start-regexp nil t)
-          (setq ff-function-name (buffer-substring (match-beginning 0)
-                                                   (match-end 0)))
-        ))))
-
-;; bind with (setq ff-post-load-hooks 'ff-set-point-accordingly)
+;; bind with (setq ff-post-load-hook 'ff-set-point-accordingly)
 ;;
 (defun ff-set-point-accordingly ()
   "Find the function specified in `ff-function-name'.
@@ -891,5 +966,7 @@ That name was previously determined by `ff-which-function-are-we-in'."
         (goto-char (point-min))
         (search-forward ff-function-name nil t))))
 
-;; find-file.el ends here
+(provide 'find-file)
 
+;; arch-tag: 5a2fc49e-3b0a-4708-9acf-fb14e471a97a
+;;; find-file.el ends here