Commits

adrian  committed 84645ff

[PATCH] packages: Sync of clearcase.el with upstream version <7k321cu9.fsf@smtpmail.t-online.de>

  • Participants
  • Parent commits d93f59e

Comments (0)

Files changed (2)

+2003-10-18  Adrian Aichner  <adrian@xemacs.org>
+
+	* clearcase.el: Sync with upstream version /main/laptop/116.
+	* clearcase.el (clearcase-version-stamp):
+	* clearcase.el (clearcase-submit-bug-report):
+	* clearcase.el (clearcase-on-mswindows):
+	* clearcase.el (clearcase-on-cygwin32): Removed.
+	* clearcase.el (clearcase-on-cygwin): New.
+	* clearcase.el (clearcase-set-to-new-activity): New.
+	* clearcase.el (clearcase-prompt-for-activity-names): New.
+	* clearcase.el (clearcase-dired-reformat-buffer): Typo fix for
+	/main/laptop/116.
+	* clearcase.el (clearcase-path-follow-if-vob-slink): New.
+	* clearcase.el (clearcase-dired-list-checkouts):
+	* clearcase.el (clearcase-dired-list-checkouts-experimental):
+	* clearcase.el (clearcase-dired-list-hijacks):
+	* clearcase.el (clearcase-edcs-edit):
+	* clearcase.el (clearcase-edcs-save):
+	* clearcase.el (clearcase-read-new-activity-name): New.
+	* clearcase.el (clearcase-read-mkact-args): New.
+	* clearcase.el (clearcase-make-internally-named-activity): New.
+	* clearcase.el (clearcase-ucm-mkact-current-dir):
+	* clearcase.el (clearcase-ucm-mkact-named-current-dir): Removed.
+	* clearcase.el (clearcase-ucm-set-activity):
+	* clearcase.el (clearcase-next-action):
+	* clearcase.el (clearcase-compute-next-action):
+	* clearcase.el (clearcase-applet-diff-file-with-version):
+	* clearcase.el (clearcase-diff-file-with-version):
+	* clearcase.el (clearcase-applet-vtree-browser):
+	* clearcase.el (clearcase-applet-clearexplorer): New.
+	* clearcase.el (clearcase-uncheckout):
+	* clearcase.el (clearcase-commented-mkbrtype):
+	* clearcase.el (clearcase-browse-vtree):
+	* clearcase.el (clearcase-list-history):
+	* clearcase.el (clearcase-diff-files):
+	* clearcase.el (clearcase-fprop-unparse-properties):
+	* clearcase.el (clearcase-fprop-canonicalise-path):
+	* clearcase.el (clearcase-fprop-vob-slink-text): New.
+	* clearcase.el (clearcase-fprop-file-is-vob-slink-p): New.
+	* clearcase.el (clearcase-fprop-fmt-string): Regexp fix for
+	/main/laptop/116.
+	* clearcase.el (clearcase-vprop-timer-function): Fix for
+	/main/laptop/116 to not the properties for nil viewtag.
+	* clearcase.el (clearcase-vprop-activities):
+	* clearcase.el (clearcase-lsstream-fmt-string):
+	* clearcase.el (clearcase-vprop-read-properties):
+	* clearcase.el (clearcase-vprop-finish-reading-activities):
+	* clearcase.el (clearcase-file-appears-modified-since-checkout-p):
+	* clearcase.el (clearcase-viewdat-to-uuid):
+	* clearcase.el (clearcase-view-uuid-to-tag):
+	* clearcase.el (clearcase-file-is-in-view-p):
+	* clearcase.el (clearcase-ct-start-cleartool):
+	* clearcase.el (clearcase-ct-sentinel): New.
+	* clearcase.el (clearcase-ct-do-cleartool-command):
+	* clearcase.el (clearcase-ct-cd):
+	* clearcase.el (clearcase-ct-blocking-call):
+	* clearcase.el (clearcase-viewtag-start-view):
+	* clearcase.el (clearcase-vxpath-of-branch-base):
+	* clearcase.el (clearcase-vxpath-get-version-in-buffer):
+	* clearcase.el (clearcase-path-canonical):
+	* clearcase.el (clearcase-path-native):
+	* clearcase.el (clearcase-buffer-revert):
+	* clearcase.el (clearcase-utl-filetimes-close): New.
+	* clearcase.el (clearcase-menu-contents-minimised):
+	* clearcase.el (clearcase-menu-contents):
+	* clearcase.el (clearcase-dired-menu-contents-minimised):
+	* clearcase.el (clearcase-dired-menu-contents):
+	* clearcase.el (clearcase-get-version-string):
+	* clearcase.el (clearcase-non-lt-registry-server-online-p):
+	* clearcase.el (clearcase-lt-registry-server-online-p):
+	* clearcase.el (clearcase-hook-find-file-hook):
+	* clearcase.el (clearcase-hook-vxpath-find-file-hook):
+	* clearcase.el (clearcase-suppress-vc-within-mvfs-file-name-handler): Removed.
+	* clearcase.el (clearcase-vxpath-file-name-handler):
+	* clearcase.el (vc-registered): New.
+	* clearcase.el ('clearcase-install): New.  Prepare for XEmacs 21.5
+	behavior support.
+	* clearcase.el ('clearcase-uninstall): New.  Ditto.
+	* clearcase.el (clearcase-integrate): Add autoload cookie.
+	* clearcase.el (clearcase-unintegrate): Ditto.
+	* clearcase.el (clearcase-v6): New.
+
 2003-03-09  Ben Wing  <ben@xemacs.org>
 
 	* Makefile:

File clearcase.el

 ;;; clearcase.el --- ClearCase/Emacs integration.
 
+;; Copyright (C) 1999, 2000, 2001, 2002 Kevin Esler
+
+;; Author: Kevin Esler <esler@rational.com>
+;; Maintainer: Kevin Esler <esler@rational.com>
+;; Keywords: clearcase tools
+;; Web home: http://members.verizon.net/~vze24fr2/EmacsClearCase
+
+;; This file is not part of GNU Emacs.
+;;
+;; This program is free software; you can redistribute it and/or modify it under
+;; the terms of the GNU General Public License as published by the Free Software
+;; Foundation; either version 2, or (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+;; FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+;; details.
+
+;; 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.
+
 ;;{{{ Introduction
 
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
 ;; This is a ClearCase/Emacs integration.
 ;;
-;; Author: esler@rational.com
+
 ;;
 ;; How to use
 ;; ==========
 
 ;;{{{ Version info
 
-(defconst clearcase-version-stamp "ClearCase-version: </main/188>")
+(defconst clearcase-version-stamp "ClearCase-version: </main/laptop/116>")
 (defconst clearcase-version (substring clearcase-version-stamp 19))
-(defconst clearcase-maintainer-address "esler@rational.com")
+
+(defun clearcase-maintainer-address ()
+  ;; Avoid spam.
+  ;;
+  (concat "kevin.esler.1989"
+          "@"
+          "alum.bu.edu"))
+
 (defconst clearcase-xemacs-package-maintainer-address
   "Michael Diers <mdiers@xemacs.org>, xemacs-beta@xemacs.org")
+
 (defun clearcase-submit-bug-report ()
   "Submit via mail a bug report on ClearCase Mode"
   (interactive)
           clearcase-v3
           clearcase-v4
           clearcase-v5
+          clearcase-v6
           clearcase-servers-online
           clearcase-disable-tq
-          clearcase-on-cygwin32
+          clearcase-on-cygwin
           clearcase-setview-root
           clearcase-suppress-vc-within-mvfs
           shell-file-name
 
 (defvar clearcase-xemacs-p (string-match "XEmacs" emacs-version))
 
-(defvar clearcase-on-mswindows (memq system-type '(windows-nt ms-windows cygwin32)))
-
-(defvar clearcase-on-cygwin32 (eq system-type 'cygwin32))
+(defvar clearcase-on-mswindows (memq system-type
+                                     '(windows-nt ms-windows cygwin cygwin32)))
+
+(defvar clearcase-on-cygwin (memq system-type '(cygwin cygwin32)))
 
 (defun clearcase-view-mode-quit (buf)
   "Exit from View mode, restoring the previous window configuration."
 
 (defgroup clearcase () "ClearCase Options" :group 'tools :prefix "clearcase")
 
+;; nyi: We could also allow a value of 'prompt here
+;;
+(defcustom clearcase-set-to-new-activity t
+  "*If this variable is non-nil when a new activity is created, that activity
+will be set as the current activity for the view, otherwise no change is made
+to the view's current activity setting."
+  :group 'clearcase
+  :type 'boolean)
+
+(defcustom clearcase-prompt-for-activity-names t
+  "*If this variable is non-nil the user will be prompted for activity names.
+Otherwise, activity names will be generated automatically and will typically
+have the form \"activity011112.155233\". If the name entered is empty sucn an
+internal name will also be generated."
+  :group 'clearcase
+  :type 'boolean)
+
 (defcustom clearcase-make-backup-files nil
   "*If non-nil, backups of ClearCase files are made as with other files.
 If nil (the default), files under ClearCase control don't get backups."
   (let* ((checkout-list nil)
          (directory default-directory)
          subdir
-         subdir-native
-         filename
-         fullpath-native)
+         fullpath)
 
     ;; Iterate over each line in the buffer.
     ;;
       (goto-char (point-min))
       (while (not (eobp))
         (cond
-           
+
          ;; Case 1: Look for directory markers
          ;;
          ((setq subdir (dired-get-subdir))
 
-          (setq subdir-native (clearcase-path-canonicalise-slashes
-                               (clearcase-path-native subdir)))
-
           ;; We're at a subdirectory line in the dired buffer.
           ;; Go and list all checkouts in this subdirectory.
           ;;
           (setq checkout-list (clearcase-dired-list-checkouts subdir))
-            
+
           ;; If no checkouts are found, we don't need to check each file, and
           ;; it's very slow.  The checkout-list should contain something so it
           ;; doesn't attempt to do this.
           (if (null checkout-list)
               (setq checkout-list '(nil)))
           (message "Reformatting %s..." subdir))
-         
+
          ;; Case 2: Look for files (the safest way to get the filename).
          ;;
-         ((setq filename (dired-get-filename 'no-dir t))
+         ((setq fullpath (dired-get-filename nil t))
 
           ;; Expand it to get rid of . and .. entries.
           ;;
-          (setq fullpath-native (concat subdir-native filename))
+          (setq fullpath (expand-file-name fullpath))
 
           ;; Only modify directory listings of the correct format.
           ;; We replace the GID field with a checkout indicator.
                ;;     (1)     (2) (3)    (4)
                ;; -rw-rw-rw-   1 esler    5              28 Feb  2 16:02 foo.el
                "..\\([drwxlts-]+ \\) *\\([0-9]+\\) \\([^ ]+\\) *\\([^ ]+ *\\) +[0-9]+\\( [^ 0-9]+ [0-9 ][0-9] .*\\)")
-              
+
               (let* ((replacement-begin (match-beginning 4))
                      (replacement-end (match-end 4))
-                     
+
                      (replacement-length (- replacement-end replacement-begin))
                      (replacement-text (format "CHECKOUT"))
                      (is-checkout (if checkout-list
-                                      (member fullpath-native checkout-list)
-                                    (clearcase-fprop-checked-out (expand-file-name filename)))))
+                                      (member fullpath checkout-list)
+                                    (clearcase-fprop-checked-out fullpath))))
 
                 ;; Highlight the line if the file is checked-out.
                 ;;
                     ;; Replace the GID field with CHECKOUT.
                     ;;
                     (let ((buffer-read-only nil))
-                      
+
                       ;; Pad with replacement text with trailing spaces if necessary.
                       ;;
                       (if (>= replacement-length (length replacement-text))
                                                      32))))
                       (goto-char replacement-begin)
                       (delete-char replacement-length)
-                      (insert (substring replacement-text 0 replacement-length))
-
-                      ;; Highlight the checked out files.
-                      ;;
-                      (if (fboundp 'put-text-property)
-                          (put-text-property replacement-begin replacement-end
-                                             'face 'clearcase-dired-checkedout-face))))
-                ))))
-        (forward-line 1)))
-  (message "Reformatting...Done")))
+                      (insert (substring replacement-text 0 replacement-length)))
+
+                  ;; Highlight the checked out files.
+                  ;;
+                  (if (fboundp 'put-text-property)
+                      (let ((buffer-read-only nil))
+                        (put-text-property replacement-begin replacement-end
+                                           'face 'clearcase-dired-checkedout-face)))
+                  )))))
+        (forward-line 1))))
+  (message "Reformatting...Done"))
+
+
+(defun clearcase-path-follow-if-vob-slink (path)
+  (if (clearcase-fprop-file-is-vob-slink-p path)
+
+      ;; It's a slink so follow it.
+      ;;
+      (let ((slink-text (clearcase-fprop-vob-slink-text path)))
+        (if (file-name-absolute-p slink-text)
+            slink-text
+          (concat (file-name-directory path) slink-text)))
+
+    ;; Not an slink.
+    ;;
+    path))
 
 (defun clearcase-dired-list-checkouts (directory)
   "Returns a list of files checked-out to the current view in DIRECTORY."
 
-  ;; Don't bother looking for checkouts in a history-mode listing
-  ;; nor in view-private directories.
+  ;; Don't bother looking for checkouts in
+  ;;  - a history-mode branch-qua-directory
+  ;;  - a view-private directory
+  ;;
+  ;; NYI: For now don't run lsco in root of a snapshot because it gives errors.
+  ;;      We need to make this smarter.
+  ;;
+  ;; NYI: For a pathname which is a slink to a dir, despite the fact that
+  ;;      clearcase-fprop-file-is-version-p returns true, lsco fails on it,
+  ;;      with "not an element". Sheesh, surely lsco ought to follow links ?
+  ;;      Solution: catch the error and check if the dir is a slink then follow
+  ;;      the link and retry the lsco on the target.
+  ;;
+  ;;      For now just ignore the error.
   ;;
   (if (and (not (clearcase-vxpath-p directory))
-           (not (eq 'view-private-object (clearcase-fprop-mtype directory))))
+           (not (eq 'view-private-object (clearcase-fprop-mtype directory)))
+           (clearcase-fprop-file-is-version-p directory))
+
 
       (let* ((ignore (message "Listing ClearCase checkouts..."))
-             
-             (true-directory (file-truename directory))
+
+             (true-dir-path (file-truename directory))
+
+             ;; Give the directory as an argument so all names will be
+             ;; fullpaths. For some reason ClearCase adds an extra slash if you
+             ;; leave the trailing slash on the directory, so we need to remove
+             ;; it.
+             ;;
+             (native-dir-path (clearcase-path-native (directory-file-name true-dir-path)))
+
+             (followed-dir-path (clearcase-path-follow-if-vob-slink native-dir-path))
 
              ;; Form the command:
              ;;
              (cmd (list
                    "lsco" "-cview" "-fmt"
                    (if clearcase-on-mswindows
-                       (if clearcase-xemacs-p
-                           "%n\n"
-                         "%n\\n")
+                       "%n\\n"
                      "'%n\\n'")
-                   
-                   ;; Give the directory as an argument so all names will be
-                   ;; fullpaths. For some reason ClearCase adds an extra slash
-                   ;; if you leave the trailing slash on the directory, so we
-                   ;; need to remove it.
-                   ;;
-                   (clearcase-path-native (directory-file-name true-directory))))
+
+                   followed-dir-path))
 
              ;; Capture the output:
              ;;
              ;; Split the output at the newlines:
              ;;
              (checkout-list (clearcase-utl-split-string-at-char string ?\n)))
-        
+
         ;; Add entries for "." and ".." if they're checked-out.
         ;;
         (let* ((entry ".")
-               (path (expand-file-name (concat true-directory entry))))
+               (path (expand-file-name (concat (file-name-as-directory true-dir-path)
+                                               entry))))
           (if (clearcase-fprop-checked-out path)
               (setq checkout-list (cons path checkout-list))))
         (let* ((entry "..")
-               (path (expand-file-name (concat true-directory entry))))
+               (path (expand-file-name (concat (file-name-as-directory true-dir-path)
+                                               entry))))
           (if (clearcase-fprop-checked-out path)
               (setq checkout-list (cons path checkout-list))))
-        
+
+        ;; If DIRECTORY is a vob-slink, checkout list will contain pathnames
+        ;; relative to the vob-slink target rather than to DIRECTORY.  Convert
+        ;; them back here.  We're making it appear that lsco works on
+        ;; slinks-to-dirs.
+        ;;
+        (if (clearcase-fprop-file-is-vob-slink-p true-dir-path)
+            (let ((re (regexp-quote (file-name-as-directory followed-dir-path))))
+              (setq checkout-list
+                    (mapcar
+                     (function
+                      (lambda (path)
+                        (replace-regexp-in-string re true-dir-path path)))
+                     checkout-list))))
+
         (message "Listing ClearCase checkouts...done")
-        
+
         ;; Return the result.
         ;;
-        checkout-list)))
+        checkout-list)
+    ))
 
 ;; I had believed that this implementation below OUGHT to be faster, having
 ;; read the code in "ct+lsco". It seemed that "lsco -cview" hit the VOB and
            (not (eq 'view-private-object (clearcase-fprop-mtype directory))))
 
       (let* ((ignore (message "Listing ClearCase checkouts..."))
-             
+
              (true-directory (file-truename directory))
 
              ;; Move temporarily to the directory:
              ;;
              (default-directory true-directory)
-             
+
              ;; Form the command:
              ;;
              (cmd (list "ls" "-vob_only"))
                (path (expand-file-name (concat true-directory entry))))
           (if (clearcase-fprop-checked-out path)
               (setq checkout-list (cons path checkout-list))))
-        
+
         (message "Listing ClearCase checkouts...done")
-        
+
         ;; Return the result.
         ;;
         checkout-list)))
   ;;
   (let* ((true-directory (file-truename directory))
          (viewtag (clearcase-fprop-viewtag true-directory)))
-    
+
     (if (and viewtag
              (not (clearcase-vxpath-p directory))
              (not (eq 'view-private-object (clearcase-fprop-mtype directory)))
              (clearcase-file-would-be-in-snapshot-p true-directory))
-        
+
         (let* ((ignore (message "Listing ClearCase hijacks..."))
-               
+
                (true-directory (file-truename directory))
-               
+
                ;; Form the command:
                ;;
                (cmd (list
                      ;; need to remove it.
                      ;;
                      (clearcase-path-native (directory-file-name true-directory))))
-               
+
                ;; Capture the output:
                ;;
                (string (clearcase-path-canonicalise-slashes
              (line-list (clearcase-utl-split-string-at-char string ?\n))
 
              (hijack-list nil))
-          
+
           (mapcar (function
                    (lambda (line)
                      (if (string-match "^\\([^ @]+\\)@@[^ ]+ \\[hijacked\\].*" line)
                                                             (match-end 1))
                                                  hijack-list)))))
                   line-list)
-             
+
           (message "Listing ClearCase hijacks...done")
-          
+
           ;; Return the result.
           ;;
           hijack-list))))
 
 (defun clearcase-edcs-edit (tag-name)
   "Edit a ClearCase configuration specification"
+
   (interactive
    (let ((vxname (clearcase-fprop-viewtag default-directory)))
-     (list (directory-file-name
-            (completing-read "View Tag: "
-                             (clearcase-viewtag-all-viewtags-obarray)
-                             nil
-                             ;;'fascist
-                             nil
-                             vxname
-                             'clearcase-edcs-tag-history)))))
+     (if clearcase-complete-viewtags
+         (list (directory-file-name
+                (completing-read "View Tag: "
+                                 (clearcase-viewtag-all-viewtags-obarray)
+                                 nil
+                                 ;;'fascist
+                                 nil
+                                 vxname
+                                 'clearcase-edcs-tag-history)))
+       (read-string "View Tag: "))))
+
   (let ((start (current-buffer))
         (buffer-name (format "*ClearCase-Config-%s*" tag-name)))
     (kill-buffer (get-buffer-create buffer-name))
   (if (not (buffer-modified-p))
       (message "Configuration not changed since last saved")
 
+    (message "Setting configuration for %s..." clearcase-edcs-tag-name)
     (clearcase-with-tempfile
      cspec-text
-     (progn
-       (message "Setting configuration for %s..." clearcase-edcs-tag-name)
-       (write-region (point-min) (point-max) cspec-text nil 'dont-mention-it)
-       (let ((ret (clearcase-ct-cleartool-cmd "setcs"
-                                              "-tag"
-                                              clearcase-edcs-tag-name
-                                              (clearcase-path-native cspec-text))))
-         
-         ;; nyi: we could be smarter and retain viewtag info and perhaps some
-         ;;      other info. For now invalidate all cached file property info.
-         ;;
-         (clearcase-fprop-clear-all-properties)
-         
-         (set-buffer-modified-p nil)
-         (message "Setting configuration for %s...done"
-                  clearcase-edcs-tag-name))))))
+     (write-region (point-min) (point-max) cspec-text nil 'dont-mention-it)
+     (let ((ret (clearcase-ct-cleartool-cmd "setcs"
+                                            "-tag"
+                                            clearcase-edcs-tag-name
+                                            (clearcase-path-native cspec-text))))
+
+       ;; nyi: we could be smarter and retain viewtag info and perhaps some
+       ;;      other info. For now invalidate all cached file property info.
+       ;;
+       (clearcase-fprop-clear-all-properties)
+
+       (set-buffer-modified-p nil)
+       (message "Setting configuration for %s...done"
+                clearcase-edcs-tag-name)))))
 
 (defun clearcase-edcs-finish ()
   (interactive)
 
 ;;{{{ Make activity
 
-(defun clearcase-ucm-mkact-current-dir (headline &optional comment)
-  "Make an activity with HEADLINE and optional COMMENT,
-in the stream associated with the view associated with the current directory.
-The activity name is generated by ClearCase."
-  (interactive "sHeadline: ")
+(defun clearcase-read-new-activity-name ()
+  "Read the name of a new activity from the minibuffer.
+Return nil if the empty string is entered."
+
+  ;; nyi: Probably should check that the activity doesn't already exist.
+  ;;
+  (let ((entered-name (read-string "Activity name (optional): " )))
+    (if (not (zerop (length entered-name)))
+        entered-name
+      nil)))
+
+(defun clearcase-read-mkact-args ()
+  "Read the name and headline arguments for clearcase-ucm-mkact-current-dir
+from the minibuffer."
+
+  (let ((name nil)
+        (headline ""))
+    (if clearcase-prompt-for-activity-names
+        (setq name (clearcase-read-new-activity-name)))
+    (setq headline (read-string "Activity headline: " ))
+    (list name headline)))
+
+(defun clearcase-make-internally-named-activity (stream-name comment-file)
+  "Make a new activity in STREAM-NAME with creation comment in COMMENT-FILE,
+and use an internally-generated name for the activity."
+
+  (let ((ret
+         (if clearcase-set-to-new-activity
+             (clearcase-ct-blocking-call "mkact"
+                                         "-cfile" (clearcase-path-native comment-file)
+                                         "-in" stream-name
+                                         "-force")
+           (clearcase-ct-blocking-call "mkact"
+                                       "-nset"
+                                       "-cfile" (clearcase-path-native comment-file)
+                                       "-in" stream-name
+                                       "-nset"
+                                       "-force"))))
+    (if (string-match "Created activity \"\\([^\"]+\\)\"" ret)
+        (substring ret (match-beginning 1) (match-end 1))
+      (error "Failed to create activity: %s" ret))))
+
+(defun clearcase-ucm-mkact-current-dir (name headline &optional comment)
+
+  "Make an activity with NAME and HEADLINE and optional COMMENT, in the stream
+associated with the view associated with the current directory."
+
+  (interactive (clearcase-read-mkact-args))
   (let* ((viewtag (clearcase-fprop-viewtag default-directory))
          (stream  (clearcase-vprop-stream viewtag))
          (pvob    (clearcase-vprop-pvob viewtag)))
           (clearcase-comment-start-entry (format "new-activity-%d" (random))
                                          "Enter comment for new activity."
                                          'clearcase-ucm-mkact-current-dir
-                                         (list headline)))
-      ;; ...else do the operation.
-      ;;
-      (message "Making activity...")
-      (clearcase-with-tempfile
-       comment-file
-       (let ((qualified-stream (format "%s@%s" stream pvob))
-             (quoted-headline (concat "\""
-                                      (clearcase-utl-escape-double-quotes headline)
-                                      "\"")))
-         (write-region comment nil comment-file nil 'noprint)
-         (let ((ret (clearcase-ct-blocking-call "mkact" "-cfile" (clearcase-path-native comment-file)
-                                                "-headline" headline
-                                                "-in" qualified-stream "-force"))))))
-      ;; Flush the activities for this view so they'll get refreshed when needed.
-      ;;
-      (clearcase-vprop-flush-activities viewtag)
-      
-      (message "Making activity...done"))))
-
-;; Not currently used as we prefer system-generated activity names for now.
-;;
-(defun clearcase-ucm-mkact-named-current-dir (name headline &optional comment)
-  "Make an activity with NAME and HEADLINE and optional COMMENT,
-in the stream associated with the view associated with the current directory"
-  (interactive "sActivity name: \nsHeadline: ")
-  (let* ((viewtag (clearcase-fprop-viewtag default-directory))
-         (stream  (clearcase-vprop-stream viewtag))
-         (pvob    (clearcase-vprop-pvob viewtag)))
-    (if (not (clearcase-vprop-ucm viewtag))
-        (error "View %s is not a UCM view" viewtag))
-    (if (null stream)
-        (error "View %s has no stream" viewtag))
-    (if (null stream)
-        (error "View %s has no PVOB" viewtag))
-
-    (if (null comment)
-        ;; If no comment supplied, go and get one..
-        ;;
-        (progn
-          (clearcase-comment-start-entry name
-                                         "Enter comment for new activity."
-                                         'clearcase-ucm-mkact-named-current-dir
                                          (list name headline)))
       ;; ...else do the operation.
       ;;
       (message "Making activity...")
       (clearcase-with-tempfile
        comment-file
-       (let ((qualified-name (format "%s@%s" name pvob))
-             (qualified-stream (format "%s@%s" stream pvob))
-             (quoted-headline (concat "\""
-                                      (clearcase-utl-escape-double-quotes headline)
-                                      "\"")))
-         (write-region comment nil comment-file nil 'noprint)
-         (let ((ret (clearcase-ct-blocking-call "mkact" "-cfile" (clearcase-path-native comment-file)
-                                                "-headline" quoted-headline
-                                                "-in"
-                                                qualified-stream
-                                                (if (zerop (length name))
-                                                    "-force"
-                                                  qualified-name)))))))
+       (write-region comment nil comment-file nil 'noprint)
+       (let ((qualified-stream (format "%s@%s" stream pvob)))
+         (if (stringp name)
+             (if clearcase-set-to-new-activity
+                 (clearcase-ct-blocking-call "mkact"
+                                             "-cfile" (clearcase-path-native comment-file)
+                                             "-headline" headline
+                                             "-in" qualified-stream
+                                             "-force"
+                                             name)
+               (clearcase-ct-blocking-call "mkact"
+                                           "-nset"
+                                           "-cfile" (clearcase-path-native comment-file)
+                                           "-headline" headline
+                                           "-in" qualified-stream
+                                           "-force"
+                                           name))
+           (progn
+             ;; If no name was provided we do the creation in two steps:
+             ;;   mkact -force
+             ;;   chact -headline
+             ;; to make sure we get preferred internally generated activity
+             ;; name of the form "activityNNN.MMM" rather than some horrible
+             ;; concoction based on the headline.
+             ;;
+             (let ((name (clearcase-make-internally-named-activity qualified-stream comment-file)))
+               (clearcase-ct-blocking-call "chact"
+                                           "-headline" headline
+                                           name))))))
+
+      ;; Flush the activities for this view so they'll get refreshed when needed.
+      ;;
+      (clearcase-vprop-flush-activities viewtag)
+
       (message "Making activity...done"))))
 
 ;;}}}
         (let ((id (car activity)))
           (not (string-match clearcase-rebase-id-regexp id)))))
      activities)))
-        
+
 (defun clearcase-ucm-set-activity-current-dir ()
   (interactive)
   (let* ((viewtag (clearcase-fprop-viewtag default-directory)))
       ;;
       (progn
         (message "Setting activity...")
-        (let* ((qualified-activity-name (if (string-match "@" activity-name)
-                                            activity-name
-                                          (concat activity-name "@" (clearcase-vprop-pvob viewtag))))
-               (ret (clearcase-ct-blocking-call "setactivity" "-nc" "-view"
-                                                viewtag
-                                                (if qualified-activity-name
-                                                    qualified-activity-name
-                                                  "-none"))))
+        (let ((qualified-activity-name (if (string-match "@" activity-name)
+                                           activity-name
+                                         (concat activity-name "@" (clearcase-vprop-pvob viewtag)))))
+          (clearcase-ct-blocking-call "setactivity" "-nc" "-view"
+                                      viewtag
+                                      (if qualified-activity-name
+                                          qualified-activity-name
+                                        "-none")))
         ;; Update cache
         ;;
         (clearcase-vprop-set-current-activity viewtag activity-name)
-        (message "Setting activity...done")))
-        
+        (message "Setting activity...done"))
+
     ;; Set NO activity
     ;;
     (message "Unsetting activity...")
-    (let ((ret (clearcase-ct-blocking-call "setactivity" "-nc" "-view"
-                                           viewtag "-none")))
-      ;; Update cache
-      ;;
-      (clearcase-vprop-set-current-activity viewtag nil)
-      (message "Unsetting activity...done"))))
+    (clearcase-ct-blocking-call "setactivity"
+                                "-nc"
+                                "-view" viewtag
+                                "-none")
+    ;; Update cache
+    ;;
+    (clearcase-vprop-set-current-activity viewtag nil)
+    (message "Unsetting activity...done")))
 
 ;;}}}
 
           (clearcase-uncheckout file)))
 
      ((eq action 'illegal-checkin)
-      (error "This file is checked out by %s" (clearcase-fprop-user file)))
+      (error "This file is checked out by someone else: %s" (clearcase-fprop-user file)))
 
      ((eq action 'checkin)
       (clearcase-commented-checkin file))
    ;; Case 4: file is checked-out but by somebody else using this view.
    ;;         ==> refuse to checkin
    ;;
-   ((and (clearcase-fprop-checked-out file)
+   ;; This is not reliable on some Windows installations where a user is known
+   ;; as "esler" on Unix and the ClearCase server, and "ESLER" on the Windows
+   ;; client.
+   ;;
+   ((and (not clearcase-on-mswindows)
+         (clearcase-fprop-checked-out file)
          (not (string= (user-login-name)
                        (clearcase-fprop-user file))))
     'illegal-checkin)
     (start-process-shell-command "Diff"
                                  nil
                                  applet-name
-                                 (clearcase-path-canonicalise-slashes (clearcase-path-native other-file))
-                                 (clearcase-path-canonicalise-slashes (clearcase-path-native truename)))))
+                                 other-file
+                                 truename)))
 
 ;;}}}
 
                                                     other-version)))
     (if (clearcase-file-is-in-mvfs-p truename)
         (clearcase-diff-files other-vxpath truename)
-      (let ((temp-file (clearcase-vxpath-get-version-in-temp-file other-vxpath)))
-        (clearcase-diff-files temp-file truename)
-        (delete-file temp-file)))))
+      (clearcase-diff-files (clearcase-vxpath-get-version-in-temp-file other-vxpath)
+                            truename))))
 
 ;;}}}
 
     (start-process-shell-command "Vtree_browser"
                                  nil
                                  applet-name
-                                 (clearcase-path-canonicalise-slashes
-                                  (clearcase-path-native file)))))
+                                 file)))
 
 ;;}}}
 
 ;;{{{ Other applets
 
+(defun clearcase-applet-clearexplorer ()
+  (interactive)
+  (start-process-shell-command "ClearExplorer"
+                               nil
+                               "clearexplorer"
+                               "."))
+
 (defun clearcase-applet-rebase ()
   (interactive)
   (start-process-shell-command "Rebase"
 
     ;; Resync.
     ;;
-    (clearcase-sync-from-disk file)))
+    (clearcase-sync-from-disk file t)))
 
 (defun clearcase-uncheckout-seq (files)
   "Uncheckout a sequence of FILES."
                                      (list typename))
     (clearcase-with-tempfile
      comment-file
+     (write-region comment nil comment-file nil 'noprint)
      (let ((qualified-typename typename))
-       (write-region comment nil comment-file nil 'noprint)
        (if (not (string-match "@" typename))
            (setq qualified-typename
                  (format "%s@%s" typename default-directory)))
-       
+
        (clearcase-ct-cleartool-cmd "mkbrtype"
                                    "-cfile"
                                    (clearcase-path-native comment-file)
           ;; Invoke dired on the directory of the version branch.
           ;;
           (dired branch-path)
-          
+
           (clearcase-dired-sort-by-date)
 
           (if (re-search-forward (concat "[ \t]+"
 ;;{{{ List history
 
 (defun clearcase-list-history (file)
-  "List the change history of FILE."
-
-  (if (eq 'version (clearcase-fprop-mtype file))
-      (progn
-        (clearcase-ct-do-cleartool-command "lshistory" file 'unused)
-        (pop-to-buffer (get-buffer-create "*clearcase*"))
-        (setq default-directory (file-name-directory file))
-        (while (looking-at "=*\n")
-          (delete-char (- (match-end 0) (match-beginning 0)))
-          (forward-line -1))
-        (goto-char (point-min))
-        (if (looking-at "[\b\t\n\v\f\r ]+")
-            (delete-char (- (match-end 0) (match-beginning 0))))
-        (shrink-window-if-larger-than-buffer))
-    (error "%s is not a ClearCase element" file)))
+  "List the change history of FILE.
+
+FILE can be a file or a directory. If it is a directory, only the information
+on the directory element itself is listed, not on its contents."
+
+  (let ((mtype (clearcase-fprop-mtype file)))
+    (if (or (eq mtype 'version)
+            (eq mtype 'directory-version))
+        (progn
+          (message "Listing element history...")
+          (apply 'clearcase-ct-do-cleartool-command "lshistory" file 'unused
+                 (list (if (eq mtype 'directory-version) "-d")))
+          (pop-to-buffer (get-buffer-create "*clearcase*"))
+          (setq default-directory (file-name-directory file))
+          (while (looking-at "=3D*\n")
+            (delete-char (- (match-end 0) (match-beginning 0)))
+            (forward-line -1))
+          (goto-char (point-min))
+          (if (looking-at "[\b\t\n\v\f\r ]+")
+              (delete-char (- (match-end 0) (match-beginning 0))))
+          (shrink-window-if-larger-than-buffer)
+          (message "Listing element history...done"))
+      (error "%s is not a ClearCase element" file))))
 
 ;;}}}
 
 
 (defun clearcase-diff-files (file1 file2)
   "Run cleardiff on FILE1 and FILE2 and display the differences."
-  ;; Fix `file1' path since it's passed as a fully-qualified argument
-  ;; to the command. `file2' will be split into path and base name
-  ;; parts in `clearcase-do-command' which works correctly whether the
-  ;; path is native or not. If we do decide that `file2' should also
-  ;; be fixed up, the rigtht place is probably within
-  ;; `clearcase-do-command' as `file2' becomes the one known file
-  ;; argument there.
-  (let ((file1 (clearcase-path-native file1)))
-    (if clearcase-use-normal-diff
-        (clearcase-do-command 2 clearcase-normal-diff-program file2 clearcase-normal-diff-switches file1)
-      (clearcase-do-command 2 "cleardiff" file2 "-diff_format" file1))
-    (let ((diff-size (save-excursion
-                       (set-buffer "*clearcase*")
-                       (buffer-size))))
-      (if (zerop diff-size)
-          (message "No differences")
-        (clearcase-port-view-buffer-other-window "*clearcase*")
-        (goto-char 0)
-        (shrink-window-if-larger-than-buffer)))))
+  (if clearcase-use-normal-diff
+      (clearcase-do-command 2 clearcase-normal-diff-program file2 clearcase-normal-diff-switches file1)
+    (clearcase-do-command 2 "cleardiff" file2 "-diff_format" file1))
+  (let ((diff-size  (save-excursion
+                      (set-buffer "*clearcase*")
+                      (buffer-size))))
+    (if (zerop diff-size)
+        (message "No differences")
+      (clearcase-port-view-buffer-other-window "*clearcase*")
+      (goto-char 0)
+      (shrink-window-if-larger-than-buffer))))
 
 ;;}}}
 
 
 ;;{{{ File property cache
 
-;; ClearCase properties of files are stored in a vector in a hashtable
-;; with the absolute-filename (with no trailing slashes) as the lookup key.
+;; ClearCase properties of files are stored in a vector in a hashtable with the
+;; absolute-filename (with no trailing slashes) as the lookup key.
 ;;
 ;; Properties are:
 ;;
 ;; [6] oid                 : string
 ;; [7] user                : string
 ;; [8] date                : string (yyyymmdd.hhmmss)
-;; [9] time-last-described : (N, N, N) time when the properties were last read from ClearCase
+;; [9] time-last-described : (N, N, N) time when the properties were last read
+;;                           from ClearCase
 ;; [10] viewtag            : string
 ;; [11] comment            : string
+;; [12] slink-text         : string (empty string if not symlink)
 
 ;; nyi: other possible properties to record:
-;;      mtime when last described (lets us know when the cached properties might be stale)
+;;      mtime when last described (lets us know when the cached properties
+;;      might be stale)
 
 ;;{{{ Debug code
 
    (format "date:                %s\n" (aref properties 8))
    (format "time-last-described: %s\n" (current-time-string (aref properties 9)))
    (format "viewtag:             %s\n" (aref properties 10))
-   (format "comment:             %s\n" (aref properties 11))))
+   (format "comment:             %s\n" (aref properties 11))
+   (format "slink-text:          %s\n" (aref properties 12))))
 
 (defun clearcase-fprop-display-properties (file)
   "Display the recorded ClearCase properties of FILE."
 (defun clearcase-fprop-canonicalise-path (filename)
   ;; We want DIR/y and DIR\y to map to the same cache entry on ms-windows.
   ;; We want DIR and DIR/ (and on windows DIR\) to map to the same cache entry.
-  ;; 
+  ;;
   ;; However, on ms-windows avoid canonicalising X:/ to X: because, for some
   ;; reason, cleartool+desc fails on X:, but works on X:/
   ;;
   "For FILE, return its \"comment\" ClearCase property."
   (aref (clearcase-fprop-get-properties file) 11))
 
+(defun clearcase-fprop-vob-slink-text (file)
+  "For FILE, return its \"slink-text\" ClearCase property."
+  (aref (clearcase-fprop-get-properties file) 12))
+
 (defun clearcase-fprop-set-comment (file comment)
   "For FILE, set its \"comment\" ClearCase property to COMMENT."
   (aset (clearcase-fprop-get-properties file) 11 comment))
       (clearcase-fprop-user file)
     nil))
 
+(defun clearcase-fprop-file-is-vob-slink-p (object-name)
+  (not (zerop (length (clearcase-fprop-vob-slink-text object-name)))))
+
 (defun clearcase-fprop-file-is-version-p (object-name)
   (if object-name
       (let ((mtype (clearcase-fprop-mtype object-name)))
       (if clearcase-xemacs-p
           ;; XEmacs/Windows
           ;;
-	  (if clearcase-on-cygwin32
+	  (if clearcase-on-cygwin
 	      ;; Cygwin build
 	      ;;
-	      "[nil \\\"%m\\\" \\\"%f\\\" \\\"%Rf\\\" \\\"%Sn\\\" \\\"%PSn\\\" \\\"%On\\\" \\\"%u\\\" \\\"%Nd\\\" nil nil nil]\\n%c"
+	      "[nil \\\"%m\\\" \\\"%f\\\" \\\"%Rf\\\" \\\"%Sn\\\" \\\"%PSn\\\" \\\"%On\\\" \\\"%u\\\" \\\"%Nd\\\" nil nil nil \\\"%[slink_text]p\\\"]\\n%c"
 	    ;; Native build
 	    ;;
-	    ;;"\"[nil \\\"%m\\\" \\\"%f\\\" \\\"%Rf\\\" \\\"%Sn\\\" \\\"%PSn\\\" \\\"%On\\\" \\\"%u\\\" \\\"%Nd\\\" nil nil nil]\n%c\"")
-            "[nil \\\"%m\\\" \\\"%f\\\" \\\"%Rf\\\" \\\"%Sn\\\" \\\"%PSn\\\" \\\"%On\\\" \\\"%u\\\" \\\"%Nd\\\" nil nil nil]\n%c")            
+	    ;;"\"[nil \\\"%m\\\" \\\"%f\\\" \\\"%Rf\\\" \\\"%Sn\\\" \\\"%PSn\\\" \\\"%On\\\" \\\"%u\\\" \\\"%Nd\\\" nil nil nil \\\"%[slink_text]p\\\"]\n%c\"")
+            "[nil \\\"%m\\\" \\\"%f\\\" \\\"%Rf\\\" \\\"%Sn\\\" \\\"%PSn\\\" \\\"%On\\\" \\\"%u\\\" \\\"%Nd\\\" nil nil nil \\\"%[slink_text]p\\\"]\n%c")
 
         ;; GnuEmacs/Windows
         ;;
-        "[nil \"%m\" \"%f\" \"%Rf\" \"%Sn\" \"%PSn\" \"%On\" \"%u\" \"%Nd\" nil nil nil]\\n%c")
+        "[nil \"%m\" \"%f\" \"%Rf\" \"%Sn\" \"%PSn\" \"%On\" \"%u\" \"%Nd\" nil nil nil \"%[slink_text]p\"]\\n%c")
+
     ;; Unix
     ;;
-    "'[nil \"%m\" \"%f\" \"%Rf\" \"%Sn\" \"%PSn\" \"%On\" \"%u\" \"%Nd\" nil nil nil]\\n%c'")
-  
+    "'[nil \"%m\" \"%f\" \"%Rf\" \"%Sn\" \"%PSn\" \"%On\" \"%u\" \"%Nd\" nil nil nil \"%[slink_text]p\"]\\n%c'")
+
   "Format for cleartool+describe command when reading the
 ClearCase properties of a file")
 
 
 (defun clearcase-vprop-timer-function ()
   (mapcar (function (lambda (viewtag)
-                      (clearcase-vprop-get-properties viewtag)))
+                      (if viewtag (clearcase-vprop-get-properties viewtag))))
           clearcase-vprop-prefetch-queue)
   (setq clearcase-vprop-prefetch-queue nil))
 
             (message "Reading activity list...")
             (setq loop-count (1+ loop-count))
             (accept-process-output clearcase-vprop-async-proc)))
-      
+
       ;; NT synchronization with the end of the process which is reading
       ;; activities.
       ;;
             ;; so more.
             (setq loop-count (1+ loop-count))
             (sit-for 1)))))
-      
+
     (if (not (zerop loop-count))
         (message "Reading activity list...done"))
-    
+
     (aref (clearcase-vprop-get-properties viewtag) 3)))
-  
+
 (defun clearcase-vprop-current-activity (viewtag)
   "For VIEWTAG, return its \"current-activity\" ClearCase property."
   (aref (clearcase-vprop-get-properties viewtag) 4))
   "For VIEWTAG, set its \"activities\" ClearCase property to nil,
 to cause a future re-fetch."
   (clearcase-vprop-set-activities viewtag nil))
-  
+
 (defun clearcase-vprop-set-current-activity (viewtag activity)
   "For VIEWTAG, set its \"current-activity\" ClearCase property to ACTIVITY."
   (aset (clearcase-vprop-get-properties viewtag) 4 activity))
       (if clearcase-xemacs-p
           ;; XEmacs/Windows
           ;;
-	  (if clearcase-on-cygwin32
+	  (if clearcase-on-cygwin
 	      ;; Cygwin build
 	      ;;
 	      "[\\\"%n\\\"  \\\"%[master]p\\\" ]"
                  (clearcase-ct-blocking-call "lsstream" "-fmt"
                                              clearcase-lsstream-fmt-string
                                              "-view" viewtag))))
-          
+
           (setq clearcase-vprop-describe-count (1+ clearcase-vprop-describe-count))
 
           (if (setq ucm (not (zerop (length desc-string))))
                 ;; Get stream name
                 ;;
                 (setq stream (aref array-read 0))
-                
+
                 ;; Get PVOB tag from something like "unix@/vobs/projects"
                 ;;
                 (let ((s (aref array-read 1)))
                   (if (string-match "@" s)
                       (setq pvob (substring s (match-end 0)))
                     (setq pvob s)))
-          
+
                 ;; Get the activity list and store as a list of (NAME . TITLE) pairs
                 ;;
                 (setq activities (clearcase-vprop-read-activities-asynchronously viewtag))
-                
+
                 ;; Get the current activity
                 ;;
                 (let ((name-string (clearcase-ct-blocking-call "lsact" "-cact" "-fmt" "%n"
                 (aset result 4 current-activity)))
 
           (message "Reading view properties...done")))
-    
+
     result))
 
 (defvar clearcase-vprop-async-viewtag nil)
               ;; convenient when setting to an activity.
               ;;
               ;;(setq activity-list (nreverse activity-list))
-              
+
               (clearcase-vprop-set-activities clearcase-vprop-async-viewtag activity-list))
-          
+
           (kill-buffer buffer))))
     (message "Parsing view activities...done")))
 
 
 ;;{{{ Determining if a checkout was modified.
 
-;; How to tell if a file has been changed since checkout ?
-
-;; If it's size differs from pred, it changed.
-;; If we saw the first OID after checkout and it is different now, it changed
-;; Otherwise use outboard cmp routine ? Perl ?
+;; How to tell if a file changed since checkout ?
 ;;
-
-;; nyi: doesn't work; get 1-second difference,
-;; maybe because of clock skew between VOB and view ?
+;; In the worst case we actually run "ct diff -pred" but we attempt several
+;; less expensive tests first.
 ;;
-
+;;  1. If it's size differs from pred.
+;;  2. The mtime and the ctime are no longer the same.
+;;
+;; nyi: Other cheaper tests we could use:
+;;
+;;  (a) After each Emacs-driven checkout go and immediately fetch the mtime of
+;;      the file and store as fprop-checkout-mtime. Then use that to compare
+;;      against current mtime. This at least would make this function work
+;;      right on files checked out by the current Emacs process.
+;;
+;;  (b) In the MVFS, after each Emacs-driven checkout go and immediately fetch
+;;      the OID and store as fprop-checkout-oid. Then use that to compare
+;;      against the current oid (the MVFS assigns a new OID at each write).
+;;      This might not always be a win since we'd still need to run cleartool
+;;      to get the current OID.
 
 (defun clearcase-file-appears-modified-since-checkout-p (file)
   "Return whether FILE appears to have been modified since checkout.
 It doesn't examine the file contents."
 
-  (cond
-   ;; We consider various cases in order of increasing cost to compute.
-
-   ;; Case 1: it's not even checked-out.
-   ;;
-   ((not (clearcase-fprop-checked-out file))
-    nil)
-
-   ;; Case 2: the mtime and the ctime are no longer the same.
-   ;;
-   ((not (equal (clearcase-utl-file-mtime file)
-                (clearcase-utl-file-ctime file)))
-    t)
-
-   ;; Case 3: the size changed.
-   ;;
-   ((not (equal (clearcase-utl-file-size file)
-                (clearcase-utl-file-size (clearcase-vxpath-cons-vxpath
-                                          file (clearcase-fprop-predecessor-version file)))))
-    t)
-
-   ;; Case 4: the time of the checkout == the modification time of the file.
-   ;;         (Unfortunately, non-equality doesn't necessarily mean the file
-   ;;          was modified. It can sometimes be off by one second or so.)
-   ;;
-   ;; nyi: redundant case ?
-   ;;
-   ((string=
-     (clearcase-fprop-date file)
-     (clearcase-utl-emacs-date-to-clearcase-date
-      (current-time-string (nth 5 (file-attributes file)))))
-    nil)
-
-   (t
-    nil)))
-
-
-
-;; nyi: store the date property in Emacs' format to minimise
-;; format conversions ?
-;;
+  (if (not (clearcase-fprop-checked-out file))
+      nil
+
+    (let ((presumed-modified nil))
+
+      ;; We consider various cases in order of increasing cost to compute.
+
+      ;; Case 1: the size is different to its predecessor.
+      ;;
+      (if (and (clearcase-file-is-in-mvfs-p file)
+               (not
+                (equal
+                 (clearcase-utl-file-size file)
+                 ;; nyi: For the snapshot case it'd be nice to get the size of the
+                 ;;      predecessor by using "ct+desc -pred -fmt" but there doesn't
+                 ;;      seem to be a format descriptor for file size. On the other hand
+                 ;;      ct+dump can obtain the size.
+                 ;;
+                 (clearcase-utl-file-size (clearcase-vxpath-cons-vxpath
+                                           file
+                                           (clearcase-fprop-predecessor-version
+                                           file))))))
+          (setq presumed-modified 'size-changed)
+
+        ;; Case 2: the mtime and the ctime are no longer the same.
+        ;;
+        ;; nyi: At least on Windows there seems to be a small number of seconds
+        ;;      difference here even when the file is not modified.
+        ;;      So we really check to see of they are close.
+        ;;
+        (if (not (clearcase-utl-filetimes-close (clearcase-utl-file-mtime file)
+                                                (clearcase-utl-file-ctime file)
+                                                5))
+            (setq presumed-modified 'ctime-mtime-not-close)
+
+
+          ;; Case 3: last resort. Actually run a diff against predecessor.
+          ;;
+          (let ((ret (clearcase-ct-blocking-call "diff"
+                                                 "-options"
+                                                 "-quiet"
+                                                 "-pred"
+                                                 file)))
+            (if (not (zerop (length ret)))
+                (setq presumed-modified 'diffs-nonempty)))))
+
+      presumed-modified)))
 
 ;;}}}
 
 
 (defun clearcase-viewdat-to-uuid (file)
   "Extract the view-uuid from a .view.dat file."
-  ;; nyi
+  ;; nyi, but return non-nil so clearcase-file-snapshot-root works
+  t
   )
 
 (defun clearcase-view-uuid-to-tag (uuid)
   "Look up the view-uuid in the register to discover its tag."
-  ;; nyi
+  ;; nyi, but return non-nil so clearcase-file-snapshot-root works
+  t
   )
 
 ;;}}}
   (let  ((truename (file-truename (expand-file-name filename))))
     ;; Shortcut if the file is a version-extended path.
     ;;
-    (or (clearcase-vxpath-p truename)
-        (clearcase-fprop-mtype truename))))
+    (or (clearcase-file-snapshot-root truename)
+        (clearcase-vxpath-p truename)
+        (clearcase-fprop-mtype truename)
+
+        ;; nyi: How to efficiently know if we're in a dynamic-view root
+        ;;   1. Test each contained name for elementness.
+        ;;      Too inefficient.
+        ;;   2. If it is viewroot-relative.
+        ;;      Okay but not sufficient.
+        ;;      How about case v:/ when view is substed ?
+        ;;   3. We're setviewed.
+        ;;      Okay but not sufficient.
+        ;;  Maintain a cache of viewroots ?
+        )))
 
 (defun clearcase-file-viewtag (filename)
   "Find the viewtag associated with existing FILENAME."
   (accept-process-output proc timeout))
 
 (defun clearcase-ct-start-cleartool ()
+  (interactive)
   (clearcase-trace "clearcase-ct-start-cleartool()")
   (let ((process-environment (append '("ATRIA_NO_BOLD=1"
                                        "ATRIA_FORCE_GUI=1")
            (process-connection-type nil)
            (cleartool-process
             (start-process "cleartool" ;; Absolute path won't work here
-                           "*cleartool*"
+                           " *cleartool*"
                            clearcase-cleartool-path)))
       (process-kill-without-query cleartool-process)
       (setq clearcase-ct-view "")
         (message "waiting for cleartool to start...")
         (clearcase-ct-accept-process-output (tq-process clearcase-ct-tq)
                                             clearcase-ct-subproc-timeout))
+      ;; Assign a sentinel to restart it if it dies.
+      ;; nyi: This needs debugging.
+      ;;(set-process-sentinel cleartool-process 'clearcase-ct-sentinel)
+
       (clearcase-trace "clearcase-ct-start-cleartool() done")
       (message "waiting for cleartool to start...done"))))
 
+;; nyi: needs debugging.
+;;
+(defun clearcase-ct-sentinel (process event-string)
+  (clearcase-trace (format "Cleartool process sentinel called: %s" event-string))
+  (if (not (eq 'run (process-status process)))
+      (progn
+        ;; Restart the dead cleartool.
+        ;;
+        (clearcase-trace "Cleartool process restarted")
+        (clearcase-ct-start-cleartool))))
+
 (defun clearcase-ct-kill-cleartool ()
   "Kill off cleartool subprocess.  If another one is needed,
 it will be restarted.  This may be useful if you're debugging clearcase."
     (mapcar
      (function (lambda (s)
                  (and s
+                      (not (zerop (length s)))
                       (setq squeezed
                             (append squeezed (list s))))))
      flags)
 
     (clearcase-with-tempfile
      comment-file
-     (progn
-       (if (not (eq comment 'unused))
-           (if comment
-               (progn
-                 (write-region comment nil comment-file nil 'noprint)
-                 (setq squeezed (append squeezed (list "-cfile" (clearcase-path-native comment-file)))))
-             (setq squeezed (append squeezed (list "-nc")))))
-       (if file
-           (setq squeezed (append squeezed (list (clearcase-path-native file)))))
-       (let ((default-directory (file-name-directory
-                                 (or file default-directory))))
-         (clearcase-ct-cd default-directory)
-         (if clearcase-command-messages
-             (message "Running %s..." command))
-         (insert
-          (apply 'clearcase-ct-cleartool-cmd (append (list command) squeezed)))
-         (if clearcase-command-messages
-             (message "Running %s...done" command)))))
-    
+     (if (not (eq comment 'unused))
+         (if comment
+             (progn
+               (write-region comment nil comment-file nil 'noprint)
+               (setq squeezed (append squeezed (list "-cfile" (clearcase-path-native comment-file)))))
+           (setq squeezed (append squeezed (list "-nc")))))
+     (if file
+         (setq squeezed (append squeezed (list (clearcase-path-native file)))))
+     (let ((default-directory (file-name-directory
+                               (or file default-directory))))
+       (clearcase-ct-cd default-directory)
+       (if clearcase-command-messages
+           (message "Running %s..." command))
+       (insert
+        (apply 'clearcase-ct-cleartool-cmd (append (list command) squeezed)))
+       (if clearcase-command-messages
+           (message "Running %s...done" command))))
+
     (goto-char (point-min))
     (clearcase-view-mode 0 camefrom)
     (set-buffer-modified-p nil)         ; XEmacs - fsf uses `not-modified'
   (if (or (not dir)
           (string= dir clearcase-ct-wdir))
       clearcase-ct-wdir
-    (let ((ret (clearcase-ct-blocking-call "cd" (clearcase-path-native dir))))
-      (setq clearcase-ct-wdir dir))))
+    (clearcase-ct-blocking-call "cd" (clearcase-path-native dir))
+    (setq clearcase-ct-wdir dir)))
 
 (defun clearcase-ct-cleartool-cmd (&rest cmd)
   (apply 'clearcase-ct-blocking-call cmd))
         ;;
         (setq clearcase-ct-return (apply 'clearcase-ct-get-command-stdout
                                          clearcase-cleartool-path cmd))
-      
+
       ;; Use tq:
       ;;
       (setq clearcase-ct-return nil)
   (if (clearcase-viewtag-exists viewtag)
       (progn
         (message "Starting view server for %s..." viewtag)
-        (let ((ret (clearcase-ct-blocking-call "startview" viewtag)))
-          (message "Starting view server for %s...done" viewtag)))))
+        (clearcase-ct-blocking-call "startview" viewtag)
+        (message "Starting view server for %s...done" viewtag))))
 
 ;;}}}
 
 
 (defun clearcase-vxpath-of-branch-base (file)
   "Compute the version-extended pathname of the version at the branch base of FILE."
-  (let* ((file-version-path 
+  (let* ((file-version-path
           (if  (clearcase-fprop-checked-out file)
               ;; If the file is checked-out, start with its predecessor version...
               ;;
 Intended for use in snapshot views."
   (let* ((temp-file (clearcase-vxpath-get-version-in-temp-file vxpath))
          (buffer (find-file-noselect temp-file t)))
-    ;; native Windows XEmacs change:  file cannot be removed if read-only.
-    (if (not (file-writable-p temp-file))
-        (set-file-modes temp-file (+ (lsh 6 6) (lsh 6 3) (lsh 6 0))))
+
+    ;; XEmacs throws an error if you delete a read-only file
+    ;;
+    (if clearcase-xemacs-p
+        (if (not (file-writable-p temp-file))
+            (set-file-modes temp-file (string-to-number "666" 8))))
+
     (delete-file temp-file)
     buffer))
 
 (defun clearcase-path-canonical (path)
   (if (not clearcase-on-mswindows)
       path
-    (if clearcase-on-cygwin32
-	(substring (shell-command-to-string (concat "cygpath -u -p '" path "'")) 0 -1)
+    (if clearcase-on-cygwin
+	(substring (shell-command-to-string (concat "cygpath -u '" path "'")) 0 -1)
       (subst-char-in-string ?\\ ?/ path))))
 
 (defun clearcase-path-native (path)
   (if (not clearcase-on-mswindows)
       path
-    (if clearcase-on-cygwin32
-	(substring (shell-command-to-string (concat "cygpath -w -p " path)) 0 -1)
+    (if clearcase-on-cygwin
+	(substring (shell-command-to-string (concat "cygpath -w " path)) 0 -1)
       (subst-char-in-string ?/ ?\\ path))))
 
 (defun clearcase-path-file-really-exists-p (filename)
   ;; Should never call for Dired buffers
   ;;
   (assert (not (eq major-mode 'dired-mode)))
-  
+
   ;; Revert buffer, try to keep point and mark where user expects them in spite
   ;; of changes because of expanded version-control key words.  This is quite
   ;; important since otherwise typeahead won't work as expected.
 
 ;;}}}
 
+(defun clearcase-utl-filetimes-close (filetime1 filetime2 tolerance)
+  "Test if FILETIME1 and FILETIME2 are within TOLERANCE of each other."
+  ;; nyi: To do this correctly we need to know MAXINT.
+  ;; For now this is correct enough since we only use this as a guideline to
+  ;; avoid generating a diff.
+  ;;
+  (if (equal (first filetime1) (first filetime2))
+      (< (abs (- (second filetime1) (second filetime2))) tolerance)
+    nil))
+
 (defun clearcase-utl-emacs-date-to-clearcase-date (s)
   (concat
    (substring s 20);; yyyy
                               (setq answer nil))))
               (cdr l))
       answer)))
-  
+
 ;; FSF Emacs - doesn't like parameters on mark-marker.
 ;;
 (defun clearcase-utl-mark-marker ()
          :visible (clearcase-vprop-ucm (clearcase-fprop-viewtag default-directory))]
         "---------------------------------"
         (list "Applets"
-              ["Merge manager" clearcase-applet-merge-manager
+              ["ClearCase Explorer" clearcase-applet-clearexplorer
+               :keys nil
+               :visible clearcase-on-mswindows]
+              ["Project Explorer" clearcase-applet-project-explorer
                :keys nil]
-              ["Project explorer" clearcase-applet-project-explorer
+              ["Merge Manager" clearcase-applet-merge-manager
                :keys nil]
-              ["Snapshot view updater" clearcase-applet-snapshot-view-updater
+              ["Snapshot View Updater" clearcase-applet-snapshot-view-updater
                :keys nil])
         "---------------------------------"
 
          :active (clearcase-vprop-ucm (clearcase-fprop-viewtag default-directory))]
         "---------------------------------"
         (list "Applets"
-              ["Merge manager" clearcase-applet-merge-manager
+              ["ClearCase Explorer" clearcase-applet-clearexplorer
+               :keys nil
+               :active clearcase-on-mswindows]
+              ["Project Explorer" clearcase-applet-project-explorer
                :keys nil]
-              ["Project explorer" clearcase-applet-project-explorer
+              ["Merge Manager" clearcase-applet-merge-manager
                :keys nil]
-              ["Snapshot view updater" clearcase-applet-snapshot-view-updater
+              ["Snapshot View Updater" clearcase-applet-snapshot-view-updater
                :keys nil])
         "---------------------------------"
 
          :visible (clearcase-vprop-ucm (clearcase-fprop-viewtag default-directory))]
         "---------------------------------"
         (list "Applets"
-              ["Merge manager" clearcase-applet-merge-manager
+              ["ClearCase Explorer" clearcase-applet-clearexplorer
+               :keys nil
+               :visible clearcase-on-mswindows]
+              ["Project Explorer" clearcase-applet-project-explorer
                :keys nil]
-              ["Project explorer" clearcase-applet-project-explorer
+              ["Merge Manager" clearcase-applet-merge-manager
                :keys nil]
-              ["Snapshot view updater" clearcase-applet-snapshot-view-updater
+              ["Snapshot View Updater" clearcase-applet-snapshot-view-updater
                :keys nil])
         "---------------------------------"
 
          :active (clearcase-vprop-ucm (clearcase-fprop-viewtag default-directory))]
         "---------------------------------"
         (list "Applets"
-              ["Merge manager" clearcase-applet-merge-manager
+              ["ClearCase Explorer" clearcase-applet-clearexplorer
+               :keys nil
+               :active clearcase-on-mswindows]
+              ["Project Explorer" clearcase-applet-project-explorer
                :keys nil]
-              ["Project explorer" clearcase-applet-project-explorer
+              ["Merge Manager" clearcase-applet-merge-manager
                :keys nil]
-              ["Snapshot view updater" clearcase-applet-snapshot-view-updater
+              ["Snapshot View Updater" clearcase-applet-snapshot-view-updater
                :keys nil])
         "---------------------------------"
 
   ;;
   ;; The follow seems to work.
   ;;
-  (if (and clearcase-on-mswindows (not clearcase-on-cygwin32))
+  (if clearcase-on-mswindows
       (shell-command-to-string "cmd /c cleartool -version")
     (shell-command-to-string "sh -c \"cleartool -version\"")))
 
           (goto-char (point-min))
           (if (looking-at "Tag: ")
               (setq result t)))
-        (if (memq (process-status process) '(run stop))
-            (kill-process process))))
+        (condition-case nil
+            (kill-process process)
+          (error nil))))
     ;; If servers are apparently not online, keep the
     ;; buffer around so we can see what lsregion reported.
     ;;
           (goto-char (point-min))
           (if (re-search-forward "view_cache_size" nil t)
               (setq result t)))
-        (if (memq (process-status process) '(run stop))
-            (kill-process process))))
+        (condition-case nil
+            (kill-process process)
+          (error nil))))
 
     ;; If servers are apparently not online, keep the
     ;; buffer around so we can see what lssite reported.
                       (unless clearcase-make-backup-files
                         (make-local-variable 'backup-inhibited)
                         (setq backup-inhibited t))))
-                
+
                 (clearcase-set-auto-mode)))))))
 
 (defun clearcase-set-auto-mode ()
                        clearcase-vxpath-glue
                        version
                        (buffer-name))))
-          
+
           (or (string= new-buffer-name (buffer-name))
-              
+
               ;; Uniquify the name, if necessary.
               ;;
               (let ((n 2)
         ;;
         (let ((new-dir (file-name-directory element)))
           (setq default-directory new-dir))
-        
+
         ;; 3. Disable auto-saving.
         ;;
         ;; If we're visiting <filename>@@/<branch path>/199
 ;;{{{ A write-file-hook to auto-insert a version-string.
 
 ;; To use this, put a line containing this in the first 8 lines of your file:
-;;    ClearCase-version: </main/laptop/82>
+;;    ClearCase-version: </main/laptop/115>
 ;; and make sure that clearcase-version-stamp-active gets set to true at least
 ;; locally in the file.
 
 
 (defun clearcase-version-stamp ()
   (interactive)
-  (if (and clearcase-version-stamp-active
+  (if (and clearcase-mode
+           clearcase-version-stamp-active
            (file-exists-p buffer-file-name)
            (equal 'version (clearcase-fprop-mtype buffer-file-name)))
       (let ((latest-version (clearcase-fprop-predecessor-version buffer-file-name)))
         ;; to insert the version-stamp. Folding mode really needs to supply a
         ;; 'save-folded-excursion function to solve this one.  We won't attempt
         ;; a cheaper hack here.
-            
+
         (save-excursion
           (save-restriction
             (widen)
 
 ;;}}}
 
-;;{{{ Disable VC in the MVFS
-
-;; This handler ensures that VC doesn't attempt to operate inside the MVFS.
-;; This stops it from futile searches for RCS directories and the like inside.
-;; It prevents a certain amount of clutter in the MVFS' noent-cache.
-;;
-(defun clearcase-suppress-vc-within-mvfs-file-name-handler (operation &rest args)
-  (clearcase-when-debugging
-   (if (fboundp 'clearcase-utl-syslog)
-       (clearcase-utl-syslog "*clearcase-fh-trace*"
-                             (cons "clearcase-suppress-vc-within-mvfs-file-name-handler:"
-                                   (cons operation args)))))
-  ;; Inhibit recursion:
-  ;;
-  (let ((inhibit-file-name-handlers
-         (cons 'clearcase-suppress-vc-within-mvfs-file-name-handler
-               (and (eq inhibit-file-name-operation operation)
-                    inhibit-file-name-handlers)))
-        (inhibit-file-name-operation operation))
-
-    (cond
-     ((and (eq operation 'vc-registered)
-           (clearcase-file-would-be-in-view-p (car args)))
-      nil)
-
-     (t
-      (apply operation args)))))
-
-;;}}}
-
-;;{{{ File name handler for version extended file names 
+;;{{{ File name handler for version extended file names
 
 ;; For version extended pathnames there are two possible answers
 ;; for each of
     (cond ((eq operation 'file-name-nondirectory)
 	   (file-name-nondirectory (clearcase-vxpath-element-part
 				    (car args))))
-          
+
 	  ((eq operation 'file-name-directory)
 	   (file-name-directory (clearcase-vxpath-element-part
 				 (car args))))
-          
+
 	  (t
 	   (apply operation args)))))
 
 ;;}}}
 
 ;;}}}
+;;{{{ Advice: Disable VC in the MVFS
+
+;; This handler ensures that VC doesn't attempt to operate inside the MVFS.
+;; This stops it from futile searches for RCS directories and the like inside.
+;; It prevents a certain amount of clutter in the MVFS' noent-cache.
+;;
+
+(defadvice vc-registered (around clearcase-interceptor disable compile)
+  "Disable normal behavior if in a clearcase dynamic view.
+This is enabled/disabled by clearcase-integrate/clearcase-unintegrate."
+  (if (clearcase-file-would-be-in-view-p (ad-get-arg 0))
+      nil
+    ad-do-it))
+
+;;}}}
 
 ;;{{{ Functions: integrate and un-integrate.
 
+;; APA: Prepare for XEmacs 21.5 behavior support.
+;;;###autoload
+(defalias 'clearcase-install 'clearcase-integrate)
+(defalias 'clearcase-uninstall 'clearcase-unintegrate)
+
+;;;###autoload
 (defun clearcase-integrate ()
   "Enable ClearCase integration"
   (interactive)
   ;;
   ;;    2.1 Start views when //view/TAG or m:/TAG is referenced.
   ;;
-  (if (not clearcase-on-mswindows)
-      (add-to-list 'file-name-handler-alist
-                   (cons clearcase-vrpath-regexp
-                         'clearcase-viewroot-relative-file-name-handler)))
+  (add-to-list 'file-name-handler-alist
+               (cons clearcase-vrpath-regexp
+                     'clearcase-viewroot-relative-file-name-handler))
 
   ;;    2.2 Completion on viewtags.
   ;;
   ;;    2.3 Turn off RCS/VCS/SCCS activity inside a ClearCase dynamic view.
   ;;
   (if clearcase-suppress-vc-within-mvfs
-      (add-to-list 'file-name-handler-alist
-                   (cons ".*" 'clearcase-suppress-vc-within-mvfs-file-name-handler)))
+      (when clearcase-suppress-vc-within-mvfs
+	(ad-enable-advice 'vc-registered 'around 'clearcase-interceptor)
+	(ad-activate 'vc-registered)))
 
 ;; Disabled for now. See comments above clearcase-vxpath-file-name-handler.
-;;  
+;;
 ;;   ;;    2.4 Add file name handler for version extended path names
 ;;   ;;
 ;;   (add-to-list 'file-name-handler-alist
 ;;                (cons clearcase-vxpath-glue 'clearcase-vxpath-file-name-handler))
   )
 
+;;;###autoload
 (defun clearcase-unintegrate ()
   "Disable ClearCase integration"
   (interactive)
                       (memq (cdr entry)
                             '(clearcase-viewroot-relative-file-name-handler
                               clearcase-viewtag-file-name-handler
-                              clearcase-suppress-vc-within-mvfs-file-name-handler
                               clearcase-vxpath-file-name-handler))))
-                   file-name-handler-alist)))
+                   file-name-handler-alist))
+
+  ;; 3. Turn on RCS/VCS/SCCS activity everywhere.
+  ;;
+  (ad-disable-advice 'vc-registered 'around 'clearcase-interceptor)
+  (ad-activate 'vc-registered))
 
 ;;}}}
 
 (defvar clearcase-v3 nil)
 (defvar clearcase-v4 nil)
 (defvar clearcase-v5 nil)
+(defvar clearcase-v6 nil)
 (defvar clearcase-servers-online nil)
 (defvar clearcase-setview-root nil)
 (defvar clearcase-setview-viewtag)
 (defvar clearcase-setview-viewtag nil)
 
 (progn
+  ;; If the SHELL environment variable points to the wrong place,
+  ;; call-process fails on Windows and this startup fails.
+  ;; Check for this and unset the useless EV.
+
+  (let ((shell-ev-value (getenv "SHELL")))
+    (if clearcase-on-mswindows
+        (if (stringp shell-ev-value)
+            (if (not (executable-find shell-ev-value))
+                (setenv "SHELL" nil)))))
+
   ;; Things have to be done here in a certain order.
   ;;
   ;; 1. Make sure cleartool is on the shell search PATH.
         ;;
         (setq clearcase-clearcase-version-installed (clearcase-get-version-string))
         (setq clearcase-lt
-              (not (null (string-match "^ClearCase LT"
+              (not (null (string-match "ClearCase LT"
                                        clearcase-clearcase-version-installed))))
         (setq clearcase-v3
               (not (null (string-match "^ClearCase version 3"
         (setq clearcase-v5
               (not (null (string-match "^ClearCase \\(LT \\)?version 2002.05"
                                        clearcase-clearcase-version-installed))))
-        
+        (setq clearcase-v6
+              (not (null (string-match "^ClearCase \\(LT \\)?version 2003.06"
+                                       clearcase-clearcase-version-installed))))
+
         ;; 3. Gather setview information:
         ;;
         (if (setq clearcase-setview-root (if (not clearcase-on-mswindows)
                                              (getenv "CLEARCASE_ROOT")))
             (setq clearcase-setview-viewtag
                   (file-name-nondirectory clearcase-setview-root)))
-        
+
         ;; 4. Discover if the servers appear to be online.
         ;;
         (setq clearcase-servers-online (clearcase-registry-server-online-p))
-        
+
         (if clearcase-servers-online
-            
+
             ;; 5. Everything seems in place to ensure that ClearCase mode will
             ;;    operate correctly, so integrate now.
             ;;