Commits

berndl  committed 082cf12

synced with current upstream 2.31

  • Participants
  • Parent commits 055c5ad

Comments (0)

Files changed (15)

+2004-12-10  Klaus Berndl  <klaus.berndl@sdm.de>
+	
+	* Sync with current upstream 2.31
+
 2004-12-01  Norbert Koch  <viteno@xemacs.org>
 
 	* Makefile (VERSION): XEmacs package 1.20 released.
 # Boston, MA 02111-1307, USA.
 
 VERSION = 1.20
-AUTHOR_VERSION = 2.30.1
+AUTHOR_VERSION = 2.31
 MAINTAINER = Klaus Berndl <klaus.berndl@sdm.de>
 PACKAGE = ecb
 PKG_TYPE = regular

File Makefile.upstream

 
 # For the ECB-maintainers: Change the version-number here and not
 # elsewhere!
-ecb_VERSION=2.30.1
+ecb_VERSION=2.31
 
 include ecb-makedef.mk
 
+* Changes for ECB version 2.31
+
+** Fixed bugs
+
+*** Fixed a recently introduced bug with XEmacs and an active isearch.
+    This bug occured when a user has clicked onto a node in a tree-buffer
+    during an active isearch and it had as result completely out-of-order
+    tree-buffers. This buf is now fixed and should never occur.
+
+*** Fixed a bug concerning accessing root-drives in native window-XEmacs
+    Fixes an annoying behavior of the native windows-version of XEmacs: When a
+    path contains only a drive-letter and a : (e.g. C:) then
+    `expand-file-name' (and a lot of other file-operations) do not interpret
+    this path as root of that drive. So ECB adds temporary a trailing
+    `directory-sep-char' and calls file-operations like `expand-file-name'
+    with this new path because then `expand-file-name' treats this as root-dir
+    of that drive. For all (X)Emacs-version besides the native-windows-XEmacs
+    this fix is not needed and takes no effect.
+
+*** Better recognizing of remote CVS-root-repositories for the VC-support
+
+** Enhancement for the VC-support
+
+*** New option `ecb-vc-xemacs-exclude-remote-cvs-repository'
+    This excludes directories with a remote cvs-repository from VC-check. This
+    option takes only effect for XEmacs and is needed cause of the outdated
+    VC-package of XEmacs which offers no heuristic state-checking and also no
+    option `vc-cvs-stay-local'. So this option takes only effect if
+    `vc-cvs-stay-local' is not avaiable. In this case ECB treats directories
+    which are managed by CVS but have a remote repository as if the directory
+    would not being managed by CVS (so the files are not checked for their
+    VC-state). This is done to avoid blocking XEmacs cause of running full
+    cvs-commands (e.g. ``cvs status'') for a bunch of files over the net.
+
+*** Added beta-support for Clearcase
+    There is already an identify-backend-function `ecb-vc-dir-managed-by-CC'
+    and a check-state-function `ecb-vc-check-CC-state' and an advice for
+    `clearcase-sync-from-disk' which enable automatic state-update after
+    checkin/out. These code seems to work quite well but nevertheless there
+    are some problems so this Clearcase-support is not added per default to
+    `ecb-vc-supported-backends'.
+
+    So if you want Clearcase-support you have to customize the option
+    `ecb-vc-supported-backends' and add these functions mentioned above (the
+    advice of `clearcase-sync-from-disk' takes only effect if the function
+    `ecb-vc-dir-managed-by-CC' can be found in `ecb-vc-supported-backends' and
+    ECB is active!). But use it at your own risk. Of course the best would be
+    if a lot of people would test this Clearcase-support and fix the
+    encountered problems ;-). Thanks to David Ostrovsky for providing a first
+    implementation!
+
+
+
 * Changes for ECB version 2.30.1
 
 ** Enhancement to the automatic option-upgrading mechanism
-README for the Emacs Code Browser (ECB) version 2.30.1
+README for the Emacs Code Browser (ECB) version 2.31
 
 
 About

File RELEASE_NOTES

-This file contains some important release-notes for ECB version 2.30.1
+This file contains some important release-notes for ECB version 2.31
 
 General:
 --------

File ecb-common-browser.el

 (defsubst ecb-directory-sep-string (&optional refdir)
   (char-to-string (ecb-directory-sep-char refdir)))   
 
+
+;;; ----- Wrappers for file- and directory-operations ------
+
+(dolist (f '(file-name-nondirectory
+             file-exists-p
+             file-name-directory
+             file-readable-p
+             file-attributes
+             file-name-extension
+             file-directory-p
+             file-accessible-directory-p
+             file-name-sans-extension
+             file-writable-p
+             file-name-as-directory
+             directory-files))
+  (fset (intern (format "ecb-%s" f))
+        `(lambda (file-or-dir-name &rest args)
+           ,(format "Delegate all args to `%s' but call first `ecb-fix-path' for FILE-OR-DIR-NAME." f)
+           (apply (quote ,f) (ecb-fix-path file-or-dir-name) args))))
+
+(defun ecb-expand-file-name (name &optional default-dir)
+  "Delegate all args to `expand-file-name' but call first `ecb-fix-path' for both args."
+  (expand-file-name (ecb-fix-path name) (ecb-fix-path default-dir)))
+
 ;;; ----- Canonical filenames ------------------------------
 
 (defun ecb-fix-path (path)

File ecb-file-browser.el

 The option `ecb-prescan-directories-exclude-regexps' offers are more fine
 granularity to exclude certain directories from this prescan."
   :group 'ecb-directories
+  :group 'ecb-most-important
   :type '(radio (const :tag "Switch on" :value t)
                 (const :tag "Switch off for remote directories" :value unless-remote)
                 (const :tag "Switch off completely" :value nil)))
 state-check."
   :group 'ecb-sources
   :group 'ecb-directories
+  :group 'ecb-most-important
   :type '(radio (const :tag "Switch on" :value t)
                 (const :tag "Switch off for remote directories" :value unless-remote)
                 (const :tag "Switch off completely" :value nil)))
 See `ecb-vc-supported-backends' how to customize the VC-support itself."
   :group 'ecb-version-control
   :group 'ecb-sources
+  :group 'ecb-most-important
   :type '(radio (const :tag "Switch on" :value t)
                 (const :tag "Switch off for remote directories" :value unless-remote)
                 (const :tag "Switch off completely" :value nil)))
   :group 'ecb-sources
   :type '(repeat (regexp :tag "Directory-regexp")))
 
+(defcustom ecb-vc-xemacs-exclude-remote-cvs-repository
+  (if ecb-running-xemacs t nil)
+  "*Exclude directories with a remote cvs-repository from VC-check.
+This option takes only effect for XEmacs and is needed cause of the outdated
+VC-package of XEmacs which offers no heuristic state-checking and also no
+option `vc-cvs-stay-local'. So this option takes only effect if
+`vc-cvs-stay-local' is not avaiable. In this case ECB treats directories which
+are managed by CVS but have a remote repository as if the directory would be
+not managed by CVS \(so the files are not checked for their VC-state). This si
+done to avoid blocking XEmacs when running full cvs-commands \(e.g. \"cvs
+status\") over the net.
+
+Note: When ECB can find the option `vc-cvs-stay-local' then this option will
+automatically take no effect regardless which Emacs-version is used."
+  :group 'ecb-version-control
+  :group 'ecb-sources
+  :type 'boolean)
+
 (defsubst ecb-vc-directory-should-be-checked-p (dir)
   "Return not nil if the sources of DIR should be checked for VC-state.
 The check is performed according to the settings in the options
                                (const :tag "unknown" :value unknown)))))
 
 (defcustom ecb-vc-supported-backends
-  (if ecb-running-xemacs
-      '((ecb-vc-dir-managed-by-CVS . vc-cvs-status))
-    '((ecb-vc-dir-managed-by-CVS . ecb-vc-state)
-      (ecb-vc-dir-managed-by-RCS . ecb-vc-state)
-      (ecb-vc-dir-managed-by-SCCS . ecb-vc-state)
-      (ecb-vc-dir-managed-by-SVN . ecb-vc-state)))
+  (delq nil (if ecb-running-xemacs
+                `((ecb-vc-dir-managed-by-CVS . vc-cvs-status))
+              `((ecb-vc-dir-managed-by-CVS . ecb-vc-state)
+                (ecb-vc-dir-managed-by-RCS . ecb-vc-state)
+                (ecb-vc-dir-managed-by-SCCS . ecb-vc-state)
+                (ecb-vc-dir-managed-by-SVN . ecb-vc-state))))
   "*Define how to to identify the VC-backend and how to check the state.
 The value of this option is a list containing cons-cells where the car is a
 function which is called to identify the VC-backend for a DIRECTORY and the
 
 Default value for GNU Emacs: Support for CVS, RCS, SCCS and Subversion \(for
 the later one the most recent version of the VC-package incl. the vc-svn
-library is needed) is added per default. To identify the VC-backend the
-functions `ecb-vc-managed-by-CVS', `ecb-vc-managed-by-RCS' rsp.
-`ecb-vc-managed-by-SCCS' rsp. `ecb-vc-managed-by-SVN' are used. For all three
-backends the function `ecb-vc-state' of the VC-package is used.
+library is needed). To identify the VC-backend the functions
+`ecb-vc-managed-by-CVS', `ecb-vc-managed-by-RCS' rsp. `ecb-vc-managed-by-SCCS'
+rsp. `ecb-vc-managed-by-SVN' are used. For all four backends the function
+`ecb-vc-state' of the VC-package is used.
 
 Default value for XEmacs: XEmacs contains only a quite outdated VC-package,
 especially there is no backend-independent check-vc-state-function available
 \(like `vc-state' for GNU Emacs). Only for CVS a check-vc-state-function is
 available: `vc-cvs-status'. Therefore ECB adds per default only support for
-CVS and uses `ecb-vc-managed-by-CVS' rsp. `vc-cvs-status'.
+CVS and uses `ecb-vc-managed-by-CVS' rsp. `vc-cvs-status'. But read the
+documentation of `ecb-vc-dir-managed-by-CVS'!
 
 Example for GNU Emacs: If `vc-recompute-state' \(to get real state-values not
 only heuristic ones) should be used to check the state for CVS-managed files
 (defun ecb-files-from-cvsignore (dir)
   "Return an expanded list of filenames which are excluded by the .cvsignore
 file in current directory."
-  (let* ((fixed-path (ecb-fix-path dir))
-         (cvsignore-content (ecb-file-content-as-string
-                             (expand-file-name ".cvsignore" fixed-path)))
+  (let ((cvsignore-content (ecb-file-content-as-string
+                            (ecb-expand-file-name ".cvsignore" dir)))
         (files nil))
     (when cvsignore-content
       (dolist (f (split-string cvsignore-content))
-        (setq files (append (directory-files fixed-path nil
-                                             (wildcard-to-regexp f) t)
+        (setq files (append (ecb-directory-files dir nil
+                                                 (wildcard-to-regexp f) t)
                             files)))
       files)))
 
         ((equal sort-method 'extension)
          (function
           (lambda(a b)
-            (let ((ext-a (file-name-extension a t))
-                  (ext-b (file-name-extension b t)))
+            (let ((ext-a (ecb-file-name-extension a t))
+                  (ext-b (ecb-file-name-extension b t)))
               (if (ecb-string= ext-a ext-b ecb-sources-sort-ignore-case)
                   (ecb-string< a b ecb-sources-sort-ignore-case)
                 (ecb-string< ext-a ext-b ecb-sources-sort-ignore-case))))))
 according to `ecb-sources-sort-method'."
   (or (ecb-files-and-subdirs-cache-get dir)
       ;; dir is not cached
-      (let ((files (directory-files (ecb-fix-path dir) nil nil t))
+      (let ((files (ecb-directory-files dir nil nil t))
             (source-regexps (or (ecb-check-directory-for-source-regexps
                                  (ecb-fix-filename dir))
                                 '(("") (""))))
         ;; 2000 entries) this is the performance-bottleneck in the
         ;; file-browser of ECB.
         (dolist (file sorted-files)
-          (if (file-directory-p (ecb-fix-filename dir file))
+          (if (ecb-file-directory-p (ecb-fix-filename dir file))
               (when (not (ecb-check-dir-exclude file))
-;;                 (when (not (file-accessible-directory-p file))
+;;                 (when (not (ecb-file-accessible-directory-p file))
 ;;                   (ecb-merge-face-into-text file
 ;;                                             ecb-directory-not-accessible-face))
                 (setq subdirs (append subdirs (list file))))
   (ecb-sources-filter-by-ext
    (read-string "Insert the filter-extension without leading dot: "
                 (and node
-                     (file-name-extension (tree-node-get-data node))))))
+                     (ecb-file-name-extension (tree-node-get-data node))))))
 
 (defun ecb-sources-filter-by-regexp ()
   "Filter the sources by a regexp. Ask for the regexp."
 
 (defun ecb-get-source-name (filename)
   "Returns the source name of a file."
-  (let ((f (file-name-nondirectory filename)))
+  (let ((f (ecb-file-name-nondirectory filename)))
     (if ecb-show-source-file-extension
         f
-      (file-name-sans-extension f))))
+      (ecb-file-name-sans-extension f))))
 
 
 (defun ecb-select-source-file (filename &optional force)
 given. If FORCE is not nil then the update of the directories buffer is done
 even if current directory is equal to `ecb-path-selected-directory'."
   (save-selected-window
-    (ecb-set-selected-directory (file-name-directory filename) force)
+    (ecb-set-selected-directory (ecb-file-name-directory filename) force)
     (setq ecb-path-selected-source filename)
   
     ;; Update directory buffer
                                 (buffer-name b)
                               (ecb-get-source-name filename)))
                         (ecb-get-source-name filename)))
-              (dir (file-name-directory filename)))
+              (dir (ecb-file-name-directory filename)))
           (if (and (ecb-vc-directory-should-be-checked-p dir)
                    (ecb-vc-managed-dir-p dir))
               (ecb-vc-generate-node-name file-1
                               (if (string-match "^(.) \\(.+\\)$" r0)
                                   (match-string 1 r0)
                                 r0)))
-                        (ext-l (file-name-extension l1 t))
-                        (ext-r (file-name-extension r1 t)))
+                        (ext-l (ecb-file-name-extension l1 t))
+                        (ext-r (ecb-file-name-extension r1 t)))
                    (if (ecb-string= ext-l ext-r ecb-history-sort-ignore-case)
                        (ecb-string< l1 r1 ecb-history-sort-ignore-case)
                      (ecb-string< ext-l ext-r ecb-history-sort-ignore-case))))))
   (let ((old-children (tree-node-get-children node))
         (path (tree-node-get-data node)))
     (tree-node-set-children node nil)
-    (if (file-accessible-directory-p path)
+    (if (ecb-file-accessible-directory-p path)
         (let ((files-and-dirs (ecb-get-files-and-subdirs path)))
           (ecb-tree-node-add-files node path (cdr files-and-dirs)
                                    ecb-directories-nodetype-directory
                  (progn
                    (setq norm-dir (ecb-fix-filename path nil t))
                    (setq name (if (listp dir) (cadr dir) norm-dir))
-                   (if (file-accessible-directory-p norm-dir)
+                   (if (ecb-file-accessible-directory-p norm-dir)
                        (tree-node-add-child
                         node
                         (ecb-new-child old-children name
              (equal (cdr cache-value) show-sources))
         (car cache-value)
       (ecb-directory-empty-cache-remove dir)
-      (let ((entries (and (file-accessible-directory-p dir)
-                          (directory-files dir nil nil t)))
+      (let ((entries (and (ecb-file-accessible-directory-p dir)
+                          (ecb-directory-files dir nil nil t)))
             (just-files-means-empty (not show-sources))
             (full-file-name nil)
             (empty-p nil))
                 (dolist (e entries)
                   (when (not (member e '("." ".." "CVS")))
                     (setq full-file-name (ecb-fix-filename dir e))
-                    (if (file-directory-p full-file-name)
+                    (if (ecb-file-directory-p full-file-name)
                         (throw 'found 'nil)
                       (if (not just-files-means-empty)
                           (throw 'found 'nil)))))
           (setq curr-node (tree-buffer-get-node-at-point))
           (when (and (= (tree-node-get-type curr-node) node-type-to-check)
                      (ecb-sources-read-only-check-p
-                      (file-name-directory (tree-node-get-data curr-node))))
+                      (ecb-file-name-directory (tree-node-get-data curr-node))))
             (setq new-name (tree-node-get-name curr-node))
             (setq read-only-p
-                  (not (file-writable-p (tree-node-get-data curr-node))))
+                  (not (ecb-file-writable-p (tree-node-get-data curr-node))))
             (if read-only-p
                 (ecb-merge-face-into-text new-name
                                           ecb-source-read-only-face))
           (and last-check-time
                (or (null last-state) ;; FILE has been checked but is not in VC
                    (not (ecb-time-less-p last-check-time
-                                         (ecb-subseq (nth 5 (file-attributes file))
+                                         (ecb-subseq (nth 5 (ecb-file-attributes file))
                                                      0 2))))))
          (result nil))
     (if no-need-for-state-check-p
                                             (buffer-substring (point-min)
                                                               (point-max))))))))
 
+(defun ecb-vc-cvs-root-remote-p (root)
+  "Return not nil if ROOT is a remote CVS-repository."
+  (if (string-match "^:local:" root)
+      nil
+    (and (string-match "^\\(:ext:\\|:server:\\)?\\([^@]+@\\)?\\([^:]+\\):"
+                       root)
+         (match-string 3 root))))
+
+;; some tests:
+;; The following must all return cvs.sourceforge.net!
+;; (ecb-vc-cvs-root-remote-p ":ext:berndl@cvs.sourceforge.net:/usr/local/root")
+;; (ecb-vc-cvs-root-remote-p "berndl@cvs.sourceforge.net:/usr/local/root")
+;; (ecb-vc-cvs-root-remote-p ":ext:cvs.sourceforge.net:/usr/local/root")
+;; (ecb-vc-cvs-root-remote-p "cvs.sourceforge.net:/usr/local/root")
+;; (ecb-vc-cvs-root-remote-p ":ext:berndl@cvs.sourceforge.net:C:/local/root")
+;; (ecb-vc-cvs-root-remote-p "berndl@cvs.sourceforge.net:C:/local/root")
+;; (ecb-vc-cvs-root-remote-p ":ext:cvs.sourceforge.net:C:/local/root")
+;; (ecb-vc-cvs-root-remote-p "cvs.sourceforge.net:C:/local/root")
+;; The following has to return nil!
+;; (ecb-vc-cvs-root-remote-p "/local/root")
+;; (ecb-vc-cvs-root-remote-p ":local:C:/local/root")
+;; The following is allowed to return "C" because CVS forbids to use
+;; windows-path as root without keyword :local:!
+;; (ecb-vc-cvs-root-remote-p "C:/local/root")
 
 (defun ecb-vc-dir-managed-by-CVS (directory)
   "Return 'CVS if DIRECTORY is managed by CVS. nil if not.
 option `vc-cvs-stay-local' so the user can not work with remote
 CVS-repositories if working offline for example. So if there is no option
 `vc-cvs-stay-local' then ECB performs always the repository check mentioned
-above."
-  (and (file-exists-p (concat directory "/CVS/"))
+above and it depends on the value of `ecb-vc-xemacs-exclude-remote-repository'
+if ECB treats such a directory as managed by CVS or not!"
+  (and (ecb-file-exists-p (concat directory "/CVS/"))
        (or (ignore-errors (progn
                             (require 'vc)
                             (require 'vc-cvs)))
            (let* ((Root-content (ecb-file-content-as-string (concat directory
                                                                     "/CVS/Root")))
                   (host (and Root-content
-                             ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: This
-                             ;; regexp will fail when the user@ is not
-                             ;; contained in the Root - it can be omitted if
-                             ;; the user on the local and remote machines is
-                             ;; the same! But for now it should be enough...
-                             (string-match "@\\(.+\\):" Root-content)
-                             (match-string 1 Root-content))))
-             (when (or (null host) ;; local repository
-                       ;; vc-cvs-stay-local says VC should stay local for this
-                       ;; host
-                       (and (boundp 'vc-cvs-stay-local)
-                            (stringp vc-cvs-stay-local)
-                            (string-match vc-cvs-stay-local host))
-                       ;; the host is at least accessible
-                       (ecb-host-accessible-p host))
-               'CVS))
+                             (ecb-vc-cvs-root-remote-p Root-content))))
+             (if (and host
+                      ecb-vc-xemacs-exclude-remote-cvs-repository
+                      (not (boundp 'vc-cvs-stay-local)))
+                 nil
+               (when (or (null host) ;; local repository
+                         ;; vc-cvs-stay-local says VC should stay local for this
+                         ;; host
+                         (and (boundp 'vc-cvs-stay-local)
+                              (stringp vc-cvs-stay-local)
+                              (string-match vc-cvs-stay-local host))
+                         ;; the host is at least accessible
+                         (ecb-host-accessible-p host))
+                 'CVS)))
          ;; VC always will stay local so we are satisfied ;-)
          'CVS)))
 
 
 (defun ecb-vc-dir-managed-by-RCS (directory)
   "Return 'RCS if DIRECTORY is managed by RCS. nil if not."
-  (and (file-exists-p (concat directory "/RCS/"))
+  (and (ecb-file-exists-p (concat directory "/RCS/"))
        'RCS))
 
 (defun ecb-vc-dir-managed-by-SVN (directory)
   "Return 'SVN if DIRECTORY is managed by SVN. nil if not."
-  (and (file-exists-p (concat directory "/.svn/"))
+  (and (ecb-file-exists-p (concat directory "/.svn/"))
        (locate-library "vc-svn")
        'SVN))
 
 (defun ecb-vc-dir-managed-by-SCCS (directory)
   "Return 'SCCS if DIRECTORY is managed by SCCS. nil if not."
-  (or (and (file-exists-p (concat directory "/SCCS/")) 'SCCS)
+  (or (and (ecb-file-exists-p (concat directory "/SCCS/")) 'SCCS)
       ;; Remote SCCS project
       (let ((proj-dir (getenv "PROJECTDIR")))
         (if proj-dir
-            (and (file-exists-p (concat proj-dir "/SCCS")) 'SCCS)
+            (and (ecb-file-exists-p (concat proj-dir "/SCCS")) 'SCCS)
           nil))))
 
+;; clearcase support
+
+;; Problem: is this OK to assume, that the clearcase-specific
+;; stuff is already loaded? may be we need more checks here.
+(silentcomp-defun clearcase-file-is-in-view-p)
+(defun ecb-vc-dir-managed-by-CC (directory)
+  "Return 'CC if DIRECTORY is managed by ClearCase. nil if not."
+  (and (fboundp 'clearcase-file-is-in-view-p)
+       (if (clearcase-file-is-in-view-p directory)
+           'CC)))
+
+(silentcomp-defun clearcase-compute-next-action)
+(defun ecb-vc-check-CC-state (file)
+  "Checks the VC-state of FILE when under Control of Clearcase.
+Returns the following different state-values: 'unknown, 'up-to-date, 'edited
+and 'unlocked-changes."
+  (let ((action (and (fboundp 'clearcase-compute-next-action)
+                     (clearcase-compute-next-action file))))
+    (cond
+     ((eq action 'mkelem)
+      'unknown)
+     ((eq action 'checkout)
+      'up-to-date)
+     ((eq action 'uncheckout)
+      'edited)
+     ((eq action 'illegal-checkin)
+      ;; ??? Is OK ???
+      'unlocked-changes)
+     ((eq action 'checkin)
+      'edited))))
+
+(defadvice clearcase-sync-from-disk (after ecb)
+  "Ensures that the ECB-cache is reset and the entry for the currently
+checked-in/out or added file is cleared. Does nothing if the function
+`ecb-vc-dir-managed-by-CC' is not contained in `ecb-vc-supported-backends'!"
+  (when (assoc 'ecb-vc-dir-managed-by-CC ecb-vc-supported-backends)
+    (ecb-vc-cache-remove (ecb-fix-filename (ad-get-arg 0)))
+    (ecb-vc-reset-vc-stealthy-checks)))
+
 (defun ecb-vc-state (file)
   "Same as `vc-state' but it clears the internal caches of the VC-package for
 FILE before calling `vc-state'. Finally calls `vc-state' and returns that value."
                       (<= state lines-of-buffer))
             (goto-line state)
             (setq curr-node (tree-buffer-get-node-at-point))
-            (setq curr-dir (file-name-directory (tree-node-get-data curr-node)))
+            (setq curr-dir (ecb-file-name-directory (tree-node-get-data curr-node)))
             (when (and (= (tree-node-get-type curr-node) node-type-to-check)
                        (ecb-vc-directory-should-be-checked-p curr-dir))
               (setq vc-state-fcn (ecb-vc-get-state-fcn-for-dir curr-dir))
                 (or update-performed-for-dir
                     (setq update-performed-for-dir
                           (ecb-fix-filename
-                           (file-name-directory (tree-node-get-data curr-node)))))
+                           (ecb-file-name-directory (tree-node-get-data curr-node)))))
                 (tree-buffer-update-node
                  nil new-name
                  'use-old-value 'use-old-value 'use-old-value 'use-old-value t))
 ;;   with a good documentation what a user has to do.... ;-)
 
 
-(defconst ecb-vc-advices '((vc-checkin . after))
+(defvar ecb-vc-advices '((vc-checkin . after)
+                         (clearcase-sync-from-disk . after))
   "All advices needed for the builtin VC-support of ECB. Same format as
 `ecb-basic-adviced-functions'.")
 
   "Ensures that the ECB-cache is reset and the entry for the currently
 reverted file-buffer is cleared."
   (let ((file (ignore-errors (ecb-fix-filename buffer-file-name))))
-    (when (and file (file-exists-p file))
+    (when (and file (ecb-file-exists-p file))
       (ecb-vc-cache-remove file)
       (ecb-vc-reset-vc-stealthy-checks))))
 
       (let* ((filename (ecb-fix-filename path file))
              (file-1 (if include-extension
                          file
-                       (file-name-sans-extension file))))
+                       (ecb-file-name-sans-extension file))))
         (tree-node-add-child
          node
          (ecb-new-child
   (let* ((use-dialog-box nil)
          (my-dir (ecb-fix-filename
                   (or dir
-                      (file-name-directory (read-file-name "Add source path: ")))
+                      (ecb-file-name-directory (read-file-name "Add source path: ")))
                   nil t))
          (my-alias (or alias
                        (read-string (format "Alias for \"%s\" (empty = no alias): "
 
 (defun ecb-get-file-info-text (file)
   "Return a file-info string for a file in the ECB sources buffer"
-  (let ((attrs (file-attributes file)))
+  (let ((attrs (ecb-file-attributes file)))
     (format "%s %8s %4d %10d %s %s"
 	    (nth 8 attrs)
 	    (user-login-name (nth 2 attrs))
             (if (equal (ecb-show-node-info-what ecb-sources-buffer-name)
                        'file-info-full)
                 file
-              (file-name-nondirectory file)))
+              (ecb-file-name-nondirectory file)))
     ))
 
 
   "Creates a new sourcefile in current directory."
   (let* ((use-dialog-box nil)
          (dir (ecb-fix-filename
-               (funcall (if (file-directory-p (tree-node-get-data node))
+               (funcall (if (ecb-file-directory-p (tree-node-get-data node))
                             'identity
-                          'file-name-directory)
+                          'ecb-file-name-directory)
                         (tree-node-get-data node))))
-         (filename (file-name-nondirectory
+         (filename (ecb-file-name-nondirectory
                     (read-file-name "Source name: " (concat dir "/")))))
     (ecb-select-edit-window)
     (if (string-match "\\.java$" filename)
   (ecb-select-edit-window)
   (let* ((node-data (tree-node-get-data node))
          (default-directory (concat (ecb-fix-filename
-                                     (if (file-directory-p node-data)
+                                     (if (ecb-file-directory-p node-data)
                                          node-data
-                                       (file-name-directory node-data)))
+                                       (ecb-file-name-directory node-data)))
                                     (ecb-directory-sep-string node-data))))
     (call-interactively (if find
                             (or (and (fboundp ecb-grep-find-function)
 (defun ecb-dired-directory-internal (node &optional other)
   (ecb-select-edit-window)
   (let ((dir (ecb-fix-filename
-              (funcall (if (file-directory-p (tree-node-get-data node))
+              (funcall (if (ecb-file-directory-p (tree-node-get-data node))
                            'identity
-                         'file-name-directory)
+                         'ecb-file-name-directory)
                        (tree-node-get-data node)))))
     (ecb-with-adviced-functions
      (funcall (if other
 (tree-buffer-defpopup-command ecb-delete-source
   "Deletes current sourcefile."
   (let* ((file (tree-node-get-data node))
-         (dir (ecb-fix-filename (file-name-directory file))))
-    (when (ecb-confirm (concat "Really delete " (file-name-nondirectory file) "? "))
+         (dir (ecb-fix-filename (ecb-file-name-directory file))))
+    (when (ecb-confirm (concat "Really delete " (ecb-file-name-nondirectory file) "? "))
       (when (get-file-buffer file)
         (kill-buffer (get-file-buffer file)))
       (ecb-delete-file file)
 
 (tree-buffer-defpopup-command ecb-file-popup-vc-refresh-dir
   "Recompute the VC-state-values for the whole directory."
-  (let ((dir (ecb-fix-filename (file-name-directory (tree-node-get-data node)))))
+  (let ((dir (ecb-fix-filename (ecb-file-name-directory (tree-node-get-data node)))))
     (ecb-vc-cache-remove-files-of-dir dir)
     (ecb-vc-reset-vc-stealthy-checks)))
 
 
 (defvar ecb-sources-menu-title-creator
   (function (lambda (node)
-              (file-name-nondirectory (tree-node-get-data node))))
+              (ecb-file-name-nondirectory (tree-node-get-data node))))
   "The menu-title for the sources menu. See
 `ecb-directories-menu-title-creator'.")
 
   "Filter history entries by extension by popup."
   (let ((ext-str (read-string "Insert the filter-extension without leading dot: "
                               (and node
-                                   (file-name-extension (tree-node-get-data node))))))
+                                   (ecb-file-name-extension (tree-node-get-data node))))))
     (ecb-history-filter-by-ext ext-str)))
 
 (defun ecb-history-filter-by-regexp ()

File ecb-makedef.mk

-RM=rm -f
-CP=cp
-MV=mv -f
-MKDIR=mkdir -p
-
-EBATCH=$(EMACS) -batch -no-site-file
-
-ecb_LISP_EL=tree-buffer.el ecb-util.el ecb-mode-line.el ecb-help.el \
-            ecb-layout.el ecb-layout-defs.el ecb-navigate.el ecb.el \
-            ecb-eshell.el ecb-cycle.el ecb-face.el ecb-compilation.el \
-            ecb-upgrade.el ecb-create-layout.el silentcomp.el \
-            ecb-speedbar.el ecb-examples.el ecb-tod.el ecb-autogen.el \
-	    ecb-jde.el ecb-file-browser.el ecb-method-browser.el \
-	    ecb-winman-support.el ecb-semantic-wrapper.el \
-	    ecb-compatibility.el ecb-common-browser.el
-
-ecb_LISP_ELC=$(ecb_LISP_EL:.el=.elc)
-
-ecb_AUTOLOADS=ecb-autoloads.el
-
-ecb_ETC=NEWS README RELEASE_NOTES ecb-makedef.mk Makefile make.bat
-
-ecb_TEXI=ecb.texi
-
-ecb_INFO=$(ecb_TEXI:.texi=.info)
-ecb_HTML=$(ecb_TEXI:.texi=.html)
-ecb_HTML_DIR=html-help
-ecb_INFO_DIR=info-help
-
-ecb_DVI=$(ecb_TEXI:.texi=.dvi)
-ecb_PS=$(ecb_TEXI:.texi=.ps)
-ecb_PDF=$(ecb_TEXI:.texi=.pdf)
-
-ecb_IMAGE_DIR=ecb-images
-
-ecb_DISTRIB_FILES=$(ecb_LISP_EL) $(ecb_AUTOLOADS) $(ecb_TEXI) $(ecb_ETC)
-
+RM=rm -f
+CP=cp
+MV=mv -f
+MKDIR=mkdir -p
+
+EBATCH=$(EMACS) -batch -no-site-file
+
+ecb_LISP_EL=tree-buffer.el ecb-util.el ecb-mode-line.el ecb-help.el \
+            ecb-layout.el ecb-layout-defs.el ecb-navigate.el ecb.el \
+            ecb-eshell.el ecb-cycle.el ecb-face.el ecb-compilation.el \
+            ecb-upgrade.el ecb-create-layout.el silentcomp.el \
+            ecb-speedbar.el ecb-examples.el ecb-tod.el ecb-autogen.el \
+	    ecb-jde.el ecb-file-browser.el ecb-method-browser.el \
+	    ecb-winman-support.el ecb-semantic-wrapper.el \
+	    ecb-compatibility.el ecb-common-browser.el
+
+ecb_LISP_ELC=$(ecb_LISP_EL:.el=.elc)
+
+ecb_AUTOLOADS=ecb-autoloads.el
+
+ecb_ETC=NEWS README RELEASE_NOTES ecb-makedef.mk Makefile make.bat
+
+ecb_TEXI=ecb.texi
+
+ecb_INFO=$(ecb_TEXI:.texi=.info)
+ecb_HTML=$(ecb_TEXI:.texi=.html)
+ecb_HTML_DIR=html-help
+ecb_INFO_DIR=info-help
+
+ecb_DVI=$(ecb_TEXI:.texi=.dvi)
+ecb_PS=$(ecb_TEXI:.texi=.ps)
+ecb_PDF=$(ecb_TEXI:.texi=.pdf)
+
+ecb_IMAGE_DIR=ecb-images
+
+ecb_DISTRIB_FILES=$(ecb_LISP_EL) $(ecb_AUTOLOADS) $(ecb_TEXI) $(ecb_ETC)
+

File ecb-method-browser.el

                                               search-result n)))
                                       (if (and (cdr r)
                                                (stringp (cdr r))
-                                               (file-readable-p (cdr r)))
+                                               (ecb-file-readable-p (cdr r)))
                                           (cons (cdr r) (car r))))))
                         type-tag-numbers)))))))
 
           (progn
             (set-buffer (get-file-buffer ecb-path-selected-source))
             (let ((file (ecb--semantic-dependency-tag-file tag)))
-              (when (and file (file-exists-p file))
+              (when (and file (ecb-file-exists-p file))
                 (ecb-find-file-and-display
                  file (ecb-combine-ecb-button/edit-win-nr ecb-button edit-window-nr)))))
         (ecb-jump-to-tag filename

File ecb-speedbar.el

              (equal (selected-frame) ecb-frame)
              (window-live-p (get-buffer-window ecb-speedbar-buffer-name))
              (and item
-                  (file-exists-p item)
-                  (not (file-directory-p item))))
+                  (ecb-file-exists-p item)
+                  (not (ecb-file-directory-p item))))
         (ecb-select-edit-window))))
 
 

File ecb-upgrade.el

 
 ;; IMPORTANT: The version-number is auto-frobbed from the Makefile. Do not
 ;; change it here!
-(defconst ecb-version "2.30.1"
+(defconst ecb-version "2.31"
   "Current ECB version.")
 
 (eval-when-compile
 stealthy tasks. It can be a floating-point value in seconds. The value can
 also be changed during running ECB."
   :group 'ecb-general
+  :group 'ecb-most-important
   :type '(number :tag "Idle time before running stealthy tasks"
                  :value 1)
   :initialize 'custom-initialize-default
                                                ;; also the drive is added.
                                                (substring norm-filename 0 2)))
                                          ;; add the full directory as source-path
-                                         (file-name-directory norm-filename))))
-                     (ecb-add-source-path source-path source-path
+                                         (ecb-file-name-directory norm-filename))))
+                     (ecb-add-source-path source-path (ecb-fix-filename source-path)
                                           (not (cdr ecb-add-path-for-not-matching-files)))))
 
                ;; now we can be sure that a matching source-path exists
                (eq major-mode 'dired-mode)
                (ecb-set-selected-directory
                 (or (and (stringp dired-directory)
-                         (file-exists-p dired-directory)
+                         (ecb-file-exists-p dired-directory)
                          dired-directory)
                     (and (listp dired-directory)
                          (car dired-directory)))))
 (defun ecb-compile-file-if-necessary (file &optional force)
   "Compile the ECB-file FILE if necessary. This is done if FORCE is not nil or
 FILE.el is newer than FILE.elc or if FILE.elc doesn't exist."
-  (let ((elc-file (concat (file-name-sans-extension file) ".elc")))
+  (let ((elc-file (concat (ecb-file-name-sans-extension file) ".elc")))
     (if (or force
-	    (not (file-exists-p elc-file))
+	    (not (ecb-file-exists-p elc-file))
 	    (file-newer-than-file-p file elc-file))
         (byte-compile-file file))))
 
           (ecb-error "Incorrect requirements; check the versions of semantic, eieio and speedbar!"))
     (ecb-check-requirements))
   (let ((load-path
-	 (append (list (file-name-directory
+	 (append (list (ecb-file-name-directory
 			(or (locate-library "semantic")
 			    (ecb-error "Semantic is not in the load-path!")))
-                       (file-name-directory
+                       (ecb-file-name-directory
 			(or (locate-library "eieio")
 			    (ecb-error "Eieio is not in the load-path!")))
-                       (file-name-directory
+                       (ecb-file-name-directory
 			(or (locate-library "speedbar")
 			    (ecb-error "Speedbar is not in the load-path!")))
-		       (file-name-directory (locate-library "ecb")))
+		       (ecb-file-name-directory (locate-library "ecb")))
 		 load-path))
-	(files (directory-files (file-name-directory (locate-library "ecb"))
-				t)))
+	(files (ecb-directory-files (ecb-file-name-directory (locate-library "ecb"))
+                                    t)))
     (save-excursion
       (dolist (file files)
 	(if (and (string-match "\\(silentcomp\\|tree-buffer\\|ecb.*\\)\\.el$" file)
 @c edit the Makefile to change the version number. mechanism stolen
 @c from Tramp
 @macro ecbver{}
-2.30.1
+2.31
 @end macro
 
 
 * Remote repositories::         What you should now about this
 * Refreshing the VC-state::     How to refresh when state changed outside
 * Adding new backends::         Necessary steps for adding new backends
+* Known VC-problems::           Currently known problems of the VC-support
 
 Displaying the trees of the ECB-windows with different styles
 
 should be added at the beginning of this option.
 @end defopt
 
+@defopt vc-xemacs-exclude-remote-cvs-repository
+Exclude directories with a remote cvs-repository from VC-check. This
+option takes only effect for XEmacs and is needed cause of the
+outdated VC-package of XEmacs which offers no heuristic state-checking
+and also no option @code{vc-cvs-stay-local}. So this option takes only
+effect if @code{vc-cvs-stay-local} is not avaiable. In this case ECB
+treats directories which are managed by CVS but have a remote
+repository as if the directory would be not managed by CVS (so the
+files are not checked for their VC-state). This si done to avoid
+blocking XEmacs when running full cvs-commands (e.g. ``cvs status'')
+over the net.
+
+Note: When ECB can find the option @code{vc-cvs-stay-local} then this
+option will automatically take no effect regardless which
+Emacs-version is used.
+@end defopt
+
 
 @node Submitting problem report, Upgrading, Customizing, Top
 @chapter Submitting a problem report
 * Remote repositories::         What you should now about this
 * Refreshing the VC-state::     How to refresh when state changed outside
 * Adding new backends::         Necessary steps for adding new backends
+* Known VC-problems::           Currently known problems of the VC-support
 @end menu
 
 @node Identifying backends, Checking the state, Version-control support, Version-control support
 @code{vc-state} for GNU Emacs). Only for CVS a check-vc-state-function
 is available: @code{vc-cvs-status}. Therefore ECB adds per default
 only support for CVS and uses @code{ecb-vc-managed-by-CVS} rsp.
-@code{vc-cvs-status}.
+@code{vc-cvs-status}. See also @ref{Known VC-problems}!
 
 @node Checking the state, Remote repositories, Identifying backends, Version-control support
 @subsection How ECB checks the VC-state of a file
 exclude such directories with a remote repository from the VC-support
 of ECB and secondary the identify-backend-funtion
 @code{ecb-vc-dir-managed-by-CVS} behaves smart with that respect
-(@pxref{Identifying backends}).
+(@pxref{Identifying backends}). See also
+@code{ecb-vc-xemacs-exclude-remote-cvs-repository}!
 
 @subsubsection Remote paths and the VC-support of ECB
 
 ECB refreshes the VC-state-values of all files contained in this
 directory too.
 
-@node Adding new backends, ,Refreshing the VC-state, Version-control support
+@node Adding new backends, Known VC-problems, Refreshing the VC-state, Version-control support
 @subsection Necessary steps and informations for adding new backends
 
 There are mainly three necessary steps for adding a new@footnote{i.e.
 
 @end enumerate
 
+@node Known VC-problems, ,Adding new backends, Version-control support
+@subsection Currently know problems with the VC-support
+
+@subsubsection Remote repositories and XEmacs
+
+Currently there are mostly problems related to XEmacs - cause of its
+outdated VC-package which allows no heuristic state-computation but
+always runs ``cvs status'' to get the VC-state for a file (done by
+@code{vc-cvs-status}). This can be horrible slow for remote
+CVS-root-repositories. Now ECB performs the VC-check stealthy and only
+in idle-time of Emacs but even so XEmacs can be blocked espcially if
+the cygwin-build of XEmacs is used: This XEmacs-version is
+substantially slower concering file-operations and has sometimes a
+very slow and delayed response-behavior for mouse- and keyboard
+interrupts - so even ECB let the user interrupt by using
+@code{input-pending-p} before getting the VC-state of a file XEmacs
+sometimes does not react to such user-interrupts and seems to be
+blocked.
+
+Current solution: ECB offers the option
+@code{ecb-vc-xemacs-exclude-remote-cvs-repository} which excludes
+remote repositories from being checked. This option is per default t
+for XEmacs. Whenever XEmacs syncs up its VC-package with the Emacs one
+this option will automatically take no effect.
+
 @node Using eshell, Grepping directories, Version-control support, Tips and tricks
 @section Optimal using of eshell in ECB
 
 @item @tab @tab
 
 @item
+ECB seems to be blocked a long time.
+@tab @tab
+Maybe you use cygwin-XEmacs. Then either the empty-dir-check (see
+option @code{ecb-prescan-directories-for-emptyness}) or the VC-support
+(see @code{ecb-vc-enable-support}) can block ECB. 
+@ifinfo
+@*
+@end ifinfo
+For the latter one see @ref{Known VC-problems}.
+
+@item @tab @tab
+
+@item
 ECB seems to be blocked during the VC-state update in the
 tree-windows.
 @tab @tab

File tree-buffer.el

 
 ;; timer stuff
 
-(if (not ecb-running-xemacs)
+(if (not tree-buffer-running-xemacs)
     (progn
       (defalias 'tree-buffer-run-with-idle-timer 'run-with-idle-timer)
       (defalias 'tree-buffer-cancel-timer 'cancel-timer))
       "Remove TIMER from the list of active timers."
       (delete-itimer timer))))  
 
+;; debugging
+
+(defvar tree-buffer-debug-mode nil
+  "If not nil then all functions of tree-buffer which are debug-able write
+debug-messages to the message-log of Emacs. Ensure that this variable is opnlx
+not nil if you want find or report an error!")
+
+(defun tree-buffer-debug-error (&rest args)
+  "Run ARGS through `format' and write it to the *Messages*-buffer.
+Do nothing if `tree-buffer-debug-mode' is nil!"
+  (when tree-buffer-debug-mode
+    (message (concat (format "Tree-buffer-debug: [%s] "
+                             (format-time-string "%H:%M:%S"))
+                     (apply 'format args)))))
+
 ;; tree-buffer local variables
 (defvar tree-buffer-root nil)
 
 
 (defvar tree-buffer-enable-xemacs-image-bug-hack
   tree-buffer-running-xemacs
-  "If true then ECB tries to deal best with the XEmacs-bug to display
+  "If true then tree-buffer tries to deal best with the XEmacs-bug to display
 adjacent images not correctly. Set this to nil if your XEmacs-version has fixed
 this bug.")
 
   (when (equal 'image (tree-buffer-style))
     ;; Regular images (created with `insert-image' are intangible
     ;; which (I suppose) make them more compatible with XEmacs 21.
-    ;; Unfortunately, there is a giant pile o code dependent on the
+    ;; Unfortunately, there is a giant pile of code dependent on the
     ;; underlying text.  This means if we leave it tangible, then I
-    ;; don't have to change said giant piles o code.
+    ;; don't have to change said giant piles of code.
     (if image-icon
         (if tree-buffer-running-xemacs
             (add-text-properties (+ start len) start
                                             image)
                image)))))
 
+;; utilities
+
+(defun tree-buffer-position (seq elem)
+  "Return the position of ELEM within SEQ counting from 0. Comparison is done
+with `equal'."
+  (if (listp seq)
+      (let ((pos (- (length seq) (length (member elem seq)))))
+        (if (= pos (length seq))
+            nil
+          pos))
+    (catch 'found
+      (dotimes (i (length seq))
+        (if (equal elem (aref seq i))
+            (throw 'found i)))
+      nil)))
+
 (defun tree-buffer-nolog-message (&rest args)
   "Works exactly like `message' but does not log the message"
   (let ((msg (cond ((or (null args)
 (defun tree-buffer-get-node-name-start-point (name node)
   "Returns the buffer point where the name of the node starts."
   (let ((linenr (tree-buffer-find-node node)))
+    (tree-buffer-debug-error "tree-buffer-get-node-name-start-point: Cur-buf: %s, name: %s, linenr: %d"
+                             (current-buffer) name linenr)
     (when linenr
       (goto-line linenr)
       (beginning-of-line)
 
 (defun tree-buffer-get-node-name-end-point (name node)
   "Returns the buffer point where the name of the node ends."
+  (tree-buffer-debug-error "tree-buffer-get-node-name-end-point: Cur-buf: %s, name: %s"
+                           (current-buffer) name)
   (+ (tree-buffer-get-node-name-start-point name node)
      (length name)))
 
 (defun tree-buffer-at-expand-symbol (name node p)
+  (tree-buffer-debug-error "tree-buffer-at-expand-symbol: Cur-buf: %s, name: %s, p: %d, exp-sym-before: %s"
+                           (current-buffer) name p tree-buffer-expand-symbol-before)
   (if tree-buffer-expand-symbol-before
       (< p (1- (tree-buffer-get-node-name-start-point name node)))
     (> p (tree-buffer-get-node-name-end-point name node))))
                (funcall tree-buffer-is-click-valid-fn mouse-button
                         shift-pressed control-pressed meta-pressed
                         (buffer-name)))
+      (tree-buffer-debug-error "tree-buffer-select-1: Cur-buf: %s"
+                               (current-buffer))
       (let* ((p (point))
 	     (name-node (tree-buffer-get-name-node-at-point))
 	     (name (car name-node))
 	     (node (cdr name-node)))
         (when node
+          (tree-buffer-debug-error "tree-buffer-select-2: Cur-buf: %s"
+                                   (current-buffer))
           ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: Is this the right place
-          ;; for this?
-          (ignore-errors
-            (let ((search-nonincremental-instead nil))
-              (isearch-exit)))
+          ;; for this? probably it can cause some erros...... Yep - it causes
+          ;; serious XEmacs-sideeffects: clicking into tree-buffer doesn't
+          ;; work anymore when doing this during an active isearch! Seems that
+          ;; isearch-exit switches the current buffer so the buffer after the
+          ;; isearch-exit is not the same as before!! So we comment this out!!
+;;           (ignore-errors
+;;             (let ((search-nonincremental-instead nil))
+;;               (isearch-exit)))
+          (tree-buffer-debug-error "tree-buffer-select-3: Cur-buf: %s"
+                                   (current-buffer))
           (if (and (tree-buffer-at-expand-symbol name node p)
                    ;; if the expand-symbol is displayed before and mouse-button
                    ;; = 0, means RET is pressed, we do not toggle-expand but work
                        ;; tree-buffer-nodes which begins with the P-th element
                        ;; of tree-buffer-nodes (nthcdr P tree-buffer-nodes).
                        (or (ignore-errors
-                             (nthcdr (ecb-position (mapcar (lambda (n)
-                                                             (tree-node-get-name
-                                                              (cdr n)))
-                                                           tree-buffer-nodes)
-                                                   (tree-node-get-name start-node))
+                             (nthcdr (tree-buffer-position (mapcar (lambda (n)
+                                                                     (tree-node-get-name
+                                                                      (cdr n)))
+                                                                   tree-buffer-nodes)
+                                                           (tree-node-get-name start-node))
                                      tree-buffer-nodes))
                            tree-buffer-nodes)))
           (equal-fcn 'tree-buffer-node-data-equal-p))