(defgroup reftex): Update home page url-link.
[bpt/emacs.git] / lisp / ido.el
index 7b8e8c7..ff222b2 100644 (file)
@@ -1,7 +1,7 @@
 ;;; ido.el --- interactively do things with buffers and files.
 
 ;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-;;   2004, 2005 Free Software Foundation, Inc.
+;;   2004, 2005, 2006 Free Software Foundation, Inc.
 
 ;; Author: Kim F. Storm <storm@cua.dk>
 ;; Based on: iswitchb by Stephen Eglen <stephen@cns.ed.ac.uk>
 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 ;; Boston, MA 02110-1301, USA.
 
-;;; Acknowledgements
-
-;; Infinite amounts of gratitude goes to Stephen Eglen <stephen@cns.ed.ac.uk>
-;; who wrote iswitch-buffer mode - from which I ripped off 99% of the code
-;; for ido-switch-buffer and found the inspiration for ido-find-file.
-;; The ido package would never have existed without his work.
-
-;; Also thanks to Klaus Berndl, Rohit Namjoshi, Robert Fenk, Alex
-;; Schroeder, Bill Benedetto, Stephen Eglen, and many others for bug
-;; fixes and improvements.
-
-;;; History
-
-;; Since I discovered Stephen Eglen's excellent iswitchb package, I just
-;; couldn't live without it, but once being addicted to switching buffers
-;; with a minimum of keystrokes, I soon found that opening files in the
-;; old-fashioned way was just too slow - so I decided to write a package
-;; which could open files with the same speed and ease as iswitchb could
-;; switch buffers.
-
-;; I originally wrote a separate ifindf.el package based on a copy of
-;; iswitchb.el, which did for opening files what iswitchb did for
-;; switching buffers.  Along the way, I corrected a few errors in
-;; ifindf which could have found its way back into iswitchb, but since
-;; most of the functionality of the two package was practically
-;; identical, I decided that the proper thing to do was to merge my
-;; ifindf package back into iswitchb.
-;;
-;; This is basically what ido (interactively do) is all about; but I
-;; found it ackward to merge my changes into the "iswitchb-" namespace,
-;; so I invented a common "ido-" namespace for the merged packages.
-;;
-;; This version is based on ido.el version 1.57 released on
-;; gnu.emacs.sources adapted for emacs 22.1 to use command remapping
-;; and optionally hooking the read-buffer and read-file-name functions.
-;;
-;; Prefix matching was added by Klaus Berndl <klaus.berndl@sdm.de> based on
-;; an idea of Yuji Minejima <ggb01164@nifty.ne.jp> and his mcomplete-package.
-
 
 ;;; Commentary:
 
 ;; most recent, when I use ido-switch-buffer, I first of all get
 ;; presented with the list of all the buffers
 ;;
-;;       Buffer:  {123456,123}
+;;       Buffer: {123456 | 123}
 ;;
 ;; If I then press 2:
-;;       Buffer: 2[3]{123456,123}
+;;       Buffer: 2[3]{123456 | 123}
 ;;
 ;; The list in {...} are the matching buffers, most recent first
 ;; (buffers visible in the current frame are put at the end of the
 ;; pressing TAB.  In this case, I will get "3" added to my input.
 
 ;; So, I press TAB:
-;;      Buffer: 23{123456,123}
+;;      Buffer: 23{123456 | 123}
 ;;
 ;; At this point, I still have two matching buffers.
 ;; If I want the first buffer in the list, I simply press RET.  If I
 ;; top of the list and then RET to select it.
 ;;
 ;; However, if I type 4, I only have one match left:
-;;       Buffer: 234[123456] [Matched]
+;;       Buffer: 234[123456]
+;;
+;; Since there is only one matching buffer left, it is given in [] and
+;; it is shown in the `ido-only-match' face (ForestGreen).  I can now
+;; press TAB or RET to go to that buffer.
 ;;
-;; Since there is only one matching buffer left, it is given in [] and we
-;; see the text [Matched] afterwards.  I can now press TAB or RET to go
-;; to that buffer.
+;; If I want to create a new buffer named "234", I press C-j instead of
+;; TAB or RET.
 ;;
-;; If however, I now type "a":
+;; If instead, I type "a":
 ;;       Buffer: 234a [No match]
 ;; There are no matching buffers.  If I press RET or TAB, I can be
 ;; prompted to create a new buffer called "234a".
 ;;
 ;;(defun ido-my-keys ()
 ;;  "Add my keybindings for ido."
-;;  (define-key ido-mode-map " " 'ido-next-match)
+;;  (define-key ido-completion-map " " 'ido-next-match)
 ;;  )
 
 ;; Seeing all the matching buffers or files
 ;; can be used by other packages to read a buffer name, a file name,
 ;; or a directory name in the `ido' way.
 
+;;; Acknowledgements
+
+;; Infinite amounts of gratitude goes to Stephen Eglen <stephen@cns.ed.ac.uk>
+;; who wrote iswitch-buffer mode - from which I ripped off 99% of the code
+;; for ido-switch-buffer and found the inspiration for ido-find-file.
+;; The ido package would never have existed without his work.
+
+;; Also thanks to Klaus Berndl, Rohit Namjoshi, Robert Fenk, Alex
+;; Schroeder, Bill Benedetto, Stephen Eglen, and many others for bug
+;; fixes and improvements.
+
+;;; History
+
+;; Since I discovered Stephen Eglen's excellent iswitchb package, I just
+;; couldn't live without it, but once being addicted to switching buffers
+;; with a minimum of keystrokes, I soon found that opening files in the
+;; old-fashioned way was just too slow - so I decided to write a package
+;; which could open files with the same speed and ease as iswitchb could
+;; switch buffers.
+
+;; I originally wrote a separate ifindf.el package based on a copy of
+;; iswitchb.el, which did for opening files what iswitchb did for
+;; switching buffers.  Along the way, I corrected a few errors in
+;; ifindf which could have found its way back into iswitchb, but since
+;; most of the functionality of the two package was practically
+;; identical, I decided that the proper thing to do was to merge my
+;; ifindf package back into iswitchb.
+;;
+;; This is basically what ido (interactively do) is all about; but I
+;; found it ackward to merge my changes into the "iswitchb-" namespace,
+;; so I invented a common "ido-" namespace for the merged packages.
+;;
+;; This version is based on ido.el version 1.57 released on
+;; gnu.emacs.sources adapted for emacs 22.1 to use command remapping
+;; and optionally hooking the read-buffer and read-file-name functions.
+;;
+;; Prefix matching was added by Klaus Berndl <klaus.berndl@sdm.de> based on
+;; an idea of Yuji Minejima <ggb01164@nifty.ne.jp> and his mcomplete-package.
+
 
 ;;; Code:
 
 (provide 'ido)
 
+(defvar cua-inhibit-cua-keys)
+
 ;;; User Variables
 ;;
 ;; These are some things you might want to change.
@@ -352,10 +357,13 @@ Setting this variable directly does not take effect;
 use either \\[customize] or the function `ido-mode'."
   :set #'(lambda (symbol value)
           (ido-mode value))
-  :initialize 'custom-initialize-default
+  :initialize 'custom-initialize-set
   :require 'ido
   :link '(emacs-commentary-link "ido.el")
-  :set-after '(ido-save-directory-list-file)
+  :set-after '(ido-save-directory-list-file
+              ;; This will clear ido-unc-hosts-cache, so set it
+              ;; before loading history file.
+              ido-unc-hosts)
   :type '(choice (const :tag "Turn on only buffer" buffer)
                  (const :tag "Turn on only file" file)
                  (const :tag "Turn on both buffer and file" both)
@@ -367,7 +375,7 @@ use either \\[customize] or the function `ido-mode'."
 Setting this variable directly does not work.  Use `customize' or
 call the function `ido-everywhere'."
   :set #'(lambda (symbol value)
-          (ido-everywhere value))
+          (ido-everywhere (if value 1 -1)))
   :initialize 'custom-initialize-default
   :type 'boolean
   :group 'ido)
@@ -440,35 +448,41 @@ in merged file and directory lists."
 ;;; Examples for setting the value of ido-ignore-files
 ;(setq ido-ignore-files '("^ " "\\.c$" "\\.h$"))
 
-(defcustom ido-default-file-method  'always-frame
-    "*How to switch to new file when using `ido-find-file'.
+(defcustom ido-default-file-method  'raise-frame
+    "*How to visit a new file when using `ido-find-file'.
 Possible values:
-`samewindow'   Show new file in same window
-`otherwindow'  Show new file in another window (same frame)
-`display'      Display file in another window without switching to it
-`otherframe'   Show new file in another frame
-`maybe-frame'  If a file is visible in another frame, prompt to ask if you
-               you want to see the file in the same window of the current
-               frame or in the other frame
-`always-frame'  If a file is visible in another frame, raise that
-               frame; otherwise, visit the file in the same window"
-    :type '(choice (const samewindow)
-                  (const otherwindow)
-                  (const display)
-                  (const otherframe)
-                  (const maybe-frame)
-                  (const always-frame))
+`selected-window' Show new file in selected window
+`other-window'   Show new file in another window (same frame)
+`display'        Display file in another window without selecting to it
+`other-frame'    Show new file in another frame
+`maybe-frame'    If a file is visible in another frame, prompt to ask if you
+                 you want to see the file in the same window of the current
+                 frame or in the other frame
+`raise-frame'     If a file is visible in another frame, raise that
+                 frame; otherwise, visit the file in the same window"
+    :type '(choice (const :tag "Visit in selected window" selected-window)
+                  (const :tag "Visit in other window" other-window)
+                  (const :tag "Display (no select) in other window" display)
+                  (const :tag "Visit in other frame" other-frame)
+                  (const :tag "Ask to visit in other frame" maybe-frame)
+                  (const :tag "Raise frame if already visited" raise-frame))
     :group 'ido)
 
-(defcustom ido-default-buffer-method  'always-frame
+(defcustom ido-default-buffer-method  'raise-frame
     "*How to switch to new buffer when using `ido-switch-buffer'.
 See `ido-default-file-method' for details."
-    :type '(choice (const samewindow)
-                  (const otherwindow)
+    :type '(choice (const :tag "Show in selected window" selected-window)
+                  (const :tag "Show in other window" other-window)
+                  (const :tag "Display (no select) in other window" display)
+                  (const :tag "Show in other frame" other-frame)
+                  (const :tag "Ask to show in other frame" maybe-frame)
+                  (const :tag "Raise frame if already shown" raise-frame))
+    :type '(choice (const selected-window)
+                  (const other-window)
                   (const display)
-                  (const otherframe)
+                  (const other-frame)
                   (const maybe-frame)
-                  (const always-frame))
+                  (const raise-frame))
     :group 'ido)
 
 (defcustom ido-enable-flex-matching nil
@@ -608,6 +622,7 @@ A tramp file name uses the following syntax: /method:user@host:filename."
 
 (defcustom ido-cache-ftp-work-directory-time 1.0
   "*Maximum time to cache contents of an ftp directory (in hours).
+Use C-l in prompt to refresh list.
 If zero, ftp directories are not cached."
   :type 'number
   :group 'ido)
@@ -624,10 +639,44 @@ equivalent function, e.g. `find-file' rather than `ido-find-file'."
   :type '(repeat regexp)
   :group 'ido)
 
+(defvar ido-unc-hosts-cache t
+  "Cached value from `ido-unc-hosts' function.")
+
+(defcustom ido-unc-hosts nil
+  "*List of known UNC host names to complete after initial //.
+If value is a function, that function is called to search network for
+hosts on first use of UNC path."
+  :type '(choice (repeat :tag "List of UNC host names" string)
+                (function-item :tag "Use `NET VIEW'"
+                               :value ido-unc-hosts-net-view)
+                (function :tag "Your own function"))
+  :set #'(lambda (symbol value)
+          (set symbol value)
+          (setq ido-unc-hosts-cache t))
+  :group 'ido)
+
+(defcustom ido-downcase-unc-hosts t
+  "*Non-nil if UNC host names should be downcased."
+  :type 'boolean
+  :group 'ido)
+
+(defcustom ido-ignore-unc-host-regexps nil
+  "*List of regexps matching UNC hosts to ignore.
+Case is ignored if `ido-downcase-unc-hosts' is set."
+  :type '(repeat regexp)
+  :group 'ido)
+
+(defcustom ido-cache-unc-host-shares-time 8.0
+  "*Maximum time to cache shares of an UNC host (in hours).
+Use C-l in prompt to refresh list.
+If zero, UNC host shares are not cached."
+  :type 'number
+  :group 'ido)
+
 (defcustom ido-max-work-file-list 10
   "*Maximum number of names of recently opened files to record.
 This is the list the file names (sans directory) which have most recently
-been opened. See `ido-work-file-list' and `ido-save-directory-list-file'."
+been opened.  See `ido-work-file-list' and `ido-save-directory-list-file'."
   :type 'integer
   :group 'ido)
 
@@ -688,12 +737,17 @@ not provide the normal completion.  To show the completions, use C-a."
   :type 'boolean
   :group 'ido)
 
-(defcustom ido-enter-single-matching-directory 'slash
-  "*Automatically enter sub-directory if it is the only matching item, if non-nil.
-If value is 'slash, only enter if typing final slash, else do it always."
+(defcustom ido-enter-matching-directory 'only
+  "*Additional methods to enter sub-directory of first/only matching item.
+If value is 'first, enter first matching sub-directory when typing a slash.
+If value is 'only, typing a slash only enters the sub-directory if it is
+the only matching item.
+If value is t, automatically enter a sub-directory when it is the only
+matching item, even without typing a slash."
   :type '(choice (const :tag "Never" nil)
-                (const :tag "When typing /" slash)
-                (other :tag "Always" t))
+                (const :tag "Slash enters first directory" first)
+                (const :tag "Slash enters first and only directory" only)
+                (other :tag "Always enter unique directory" t))
   :group 'ido)
 
 (defcustom ido-create-new-buffer 'prompt
@@ -709,7 +763,7 @@ ask user whether to create buffer, or 'never to never create new buffer."
   "*Hook run after the ido variables and keymap have been setup.
 The dynamic variable `ido-cur-item' contains the current type of item that
 is read by ido, possible values are file, dir, buffer, and list.
-Additional keys can be defined in `ido-mode-map'."
+Additional keys can be defined in `ido-completion-map'."
   :type 'hook
   :group 'ido)
 
@@ -868,7 +922,7 @@ Must be set before enabling ido mode."
   :group 'ido)
 
 (defcustom ido-read-file-name-as-directory-commands '()
-  "List of commands which uses read-file-name to read a directory name.
+  "List of commands which uses `read-file-name' to read a directory name.
 When `ido-everywhere' is non-nil, the commands in this list will read
 the directory using `ido-read-directory-name'."
   :type '(repeat symbol)
@@ -891,8 +945,20 @@ The fallback command is passed as an argument to the functions."
 
 ;; Persistent variables
 
-(defvar ido-mode-map nil
-  "Keymap for `ido-find-file' and `ido-switch-buffer'.")
+(defvar ido-completion-map nil
+  "Currently active keymap for ido commands.")
+
+(defvar ido-common-completion-map nil
+  "Keymap for all ido commands.")
+
+(defvar ido-file-completion-map nil
+  "Keymap for ido file commands.")
+
+(defvar ido-file-dir-completion-map nil
+  "Keymap for ido file and directory commands.")
+
+(defvar ido-buffer-completion-map nil
+  "Keymap for ido buffer commands.")
 
 (defvar  ido-file-history nil
   "History of files selected using `ido-find-file'.")
@@ -953,7 +1019,7 @@ Copied from `icomplete-eoinput'.")
   "List of files currently matching `ido-text'.")
 
 (defvar ido-report-no-match t
-  "Report [No Match] when no completions matches ido-text.")
+  "Report [No Match] when no completions matches `ido-text'.")
 
 (defvar ido-exit nil
   "Flag to monitor how `ido-find-file' exits.
@@ -1076,10 +1142,67 @@ it doesn't interfere with other minibuffer usage.")
          (pop-to-buffer b t t)
          (setq truncate-lines t)))))
 
+(defun ido-unc-hosts (&optional query)
+  "Return list of UNC host names."
+  (let ((hosts
+        (cond
+         ((listp ido-unc-hosts)
+          ido-unc-hosts)               ;; static list or nil
+         ((listp ido-unc-hosts-cache)
+          ido-unc-hosts-cache) ;; result of net search
+         ((and query (fboundp ido-unc-hosts))
+          (message (propertize "Searching for UNC hosts..." 'face 'highlight))
+          (setq ido-unc-hosts-cache (funcall ido-unc-hosts))
+          (message nil)
+          ido-unc-hosts-cache)
+         (query
+          (setq ido-unc-hosts-cache nil))
+         (t (fboundp ido-unc-hosts)))))
+    (when query
+      (let ((case-fold-search ido-downcase-unc-hosts)
+           res host re-list re)
+       (while hosts
+         (setq host (car hosts)
+               hosts (cdr hosts)
+               re-list (and ido-process-ignore-lists
+                            ido-ignore-unc-host-regexps))
+         (while re-list
+           (setq re (car re-list)
+                 re-list (cdr re-list))
+           (if (string-match re host)
+               (setq re-list nil
+                     host nil)))
+         (when host
+           (when ido-downcase-unc-hosts
+             (setq host (downcase host)))
+           (setq res (cons host res))))
+       (setq hosts (sort res #'string<))))
+    hosts))
+
+(defun ido-unc-hosts-net-view ()
+  "Query network for list of UNC host names using `NET VIEW'."
+  (let (hosts)
+    (with-temp-buffer
+      (shell-command "net view" t)
+      (goto-char (point-min))
+      (while (re-search-forward "^\\\\\\\\\\([[:graph:]]+\\)" nil t)
+       (setq hosts (cons (match-string 1) hosts))))
+    hosts))
+
 (defun ido-is-tramp-root (&optional dir)
-  (setq dir (or dir ido-current-directory))
   (and ido-enable-tramp-completion
-       (string-match "\\`/[^/][^/]+:\\([^/:@]+@\\)?\\'" dir)))
+       (string-match "\\`/[^/]+[@:]\\'"
+                    (or dir ido-current-directory))))
+
+(defun ido-is-unc-root (&optional dir)
+  (and (ido-unc-hosts)
+       (string-equal "//"
+                    (or dir ido-current-directory))))
+
+(defun ido-is-unc-host (&optional dir)
+  (and (ido-unc-hosts)
+       (string-match "\\`//[^/]+/\\'"
+                    (or dir ido-current-directory))))
 
 (defun ido-is-root-directory (&optional dir)
   (setq dir (or dir ido-current-directory))
@@ -1126,6 +1249,12 @@ it doesn't interfere with other minibuffer usage.")
        (or (not time)
           (< (- (ido-time-stamp) time) ido-cache-ftp-work-directory-time))))
 
+(defun ido-cache-unc-valid (&optional time)
+  (and (numberp ido-cache-unc-host-shares-time)
+       (> ido-cache-unc-host-shares-time 0)
+       (or (not time)
+          (< (- (ido-time-stamp) time) ido-cache-unc-host-shares-time))))
+
 (defun ido-may-cache-directory (&optional dir)
   (setq dir (or dir ido-current-directory))
   (cond
@@ -1135,10 +1264,11 @@ it doesn't interfere with other minibuffer usage.")
         (or ido-enable-tramp-completion
             (memq system-type '(windows-nt ms-dos))))
     nil)
-   ((not (ido-is-ftp-directory dir))
-    t)
-   ((ido-cache-ftp-valid)
-    t)))
+   ((ido-is-unc-host dir)
+    (ido-cache-unc-valid))
+   ((ido-is-ftp-directory dir)
+    (ido-cache-ftp-valid))
+   (t t)))
 
 (defun ido-pp (list &optional sep)
   (let ((print-level nil) (eval-expression-print-level nil)
@@ -1159,25 +1289,22 @@ it doesn't interfere with other minibuffer usage.")
 (defun ido-save-history ()
   "Save ido history and cache information between sessions."
   (interactive)
-  (if (and ido-last-directory-list ido-save-directory-list-file)
-      (save-excursion
-       (save-window-excursion
-         (if (find-buffer-visiting ido-save-directory-list-file)
-             (kill-buffer (find-buffer-visiting ido-save-directory-list-file)))
-         (if (file-exists-p ido-save-directory-list-file)
-             (delete-file ido-save-directory-list-file))
-         (set-buffer (let ((enable-local-variables nil))
-                       (find-file-noselect ido-save-directory-list-file t)))
-         (goto-char (point-min))
-         (delete-region (point-min) (point-max))
-         (ido-pp 'ido-last-directory-list)
-         (ido-pp 'ido-work-directory-list)
-         (ido-pp 'ido-work-file-list)
-         (ido-pp 'ido-dir-file-cache "\n\n ")
-         (insert "\n")
-         (let ((version-control 'never))
+  (when (and ido-last-directory-list ido-save-directory-list-file)
+    (let ((buf (get-buffer-create " *ido session*"))
+         (version-control 'never))
+      (unwind-protect
+         (with-current-buffer buf
+           (erase-buffer)
+           (ido-pp 'ido-last-directory-list)
+           (ido-pp 'ido-work-directory-list)
+           (ido-pp 'ido-work-file-list)
+           (ido-pp 'ido-dir-file-cache "\n\n ")
+           (if (listp ido-unc-hosts-cache)
+               (ido-pp 'ido-unc-hosts-cache)
+             (insert "\n;; ----- ido-unc-hosts-cache -----\nt\n"))
+           (insert "\n")
            (write-file ido-save-directory-list-file nil))
-         (kill-buffer (current-buffer))))))
+       (kill-buffer buf)))))
 
 (defun ido-load-history (&optional arg)
   "Load ido history and cache information from previous session.
@@ -1187,18 +1314,19 @@ With prefix argument, reload history unconditionally."
       (let ((file (expand-file-name ido-save-directory-list-file))
            buf)
        (when (file-readable-p file)
-         (save-excursion
-           (save-window-excursion
-             (setq buf (set-buffer (let ((enable-local-variables nil))
-                                     (find-file-noselect file))))
-             (goto-char (point-min))
-             (condition-case nil
-                 (setq ido-last-directory-list (read (current-buffer))
-                       ido-work-directory-list (read (current-buffer))
-                       ido-work-file-list (read (current-buffer))
-                       ido-dir-file-cache (read (current-buffer)))
-               (error nil))))
-         (kill-buffer buf))))
+         (setq buf (get-buffer-create " *ido session*"))
+         (unwind-protect
+             (with-current-buffer buf
+               (erase-buffer)
+               (insert-file-contents file)
+               (condition-case nil
+                   (setq ido-last-directory-list (read (current-buffer))
+                         ido-work-directory-list (read (current-buffer))
+                         ido-work-file-list (read (current-buffer))
+                         ido-dir-file-cache (read (current-buffer))
+                         ido-unc-hosts-cache (read (current-buffer)))
+                 (error nil)))
+           (kill-buffer buf)))))
   (ido-wash-history))
 
 (defun ido-wash-history ()
@@ -1246,15 +1374,21 @@ Removes badly formatted data and ignored directories."
                            (and
                             (stringp dir)
                             (consp time)
-                            (if (integerp (car time))
-                                (and (/= (car time) 0)
-                                     (integerp (car (cdr time)))
-                                     (/= (car (cdr time)) 0)
-                                     (ido-may-cache-directory dir))
-                              (and (eq (car time) 'ftp)
-                                   (numberp (cdr time))
+                            (cond
+                             ((integerp (car time))
+                              (and (/= (car time) 0)
+                                   (integerp (car (cdr time)))
+                                   (/= (car (cdr time)) 0)
+                                   (ido-may-cache-directory dir)))
+                             ((eq (car time) 'ftp)
+                              (and (numberp (cdr time))
                                    (ido-is-ftp-directory dir)
                                    (ido-cache-ftp-valid (cdr time))))
+                             ((eq (car time) 'unc)
+                              (and (numberp (cdr time))
+                                   (ido-is-unc-host dir)
+                                   (ido-cache-unc-valid (cdr time))))
+                             (t nil))
                             (let ((s files) (ok t))
                               (while s
                                 (if (stringp (car s))
@@ -1294,8 +1428,7 @@ Removes badly formatted data and ignored directories."
          (while e
            (setq d (car e) e (cdr e))
            (if (not (consp d))
-               (set-text-properties 0 (length d) nil d))))))
-)
+               (set-text-properties 0 (length d) nil d)))))))
 
 
 (defun ido-kill-emacs-hook ()
@@ -1326,6 +1459,8 @@ This function also adds a hook to the minibuffer."
         (t nil)))
 
   (ido-everywhere (if ido-everywhere 1 -1))
+  (when ido-mode
+    (ido-init-completion-maps))
 
   (when ido-mode
     (add-hook 'minibuffer-setup-hook 'ido-minibuffer-setup)
@@ -1334,12 +1469,7 @@ This function also adds a hook to the minibuffer."
 
     (add-hook 'kill-emacs-hook 'ido-kill-emacs-hook)
 
-    (if ido-minor-mode-map-entry
-       (setcdr ido-minor-mode-map-entry (make-sparse-keymap))
-      (setq ido-minor-mode-map-entry (cons 'ido-mode (make-sparse-keymap)))
-      (add-to-list 'minor-mode-map-alist ido-minor-mode-map-entry))
-
-    (let ((map (cdr ido-minor-mode-map-entry)))
+    (let ((map (make-sparse-keymap)))
       (when (memq ido-mode '(file both))
        (define-key map [remap find-file] 'ido-find-file)
        (define-key map [remap find-file-read-only] 'ido-find-file-read-only)
@@ -1359,10 +1489,17 @@ This function also adds a hook to the minibuffer."
        (define-key map [remap switch-to-buffer-other-frame] 'ido-switch-buffer-other-frame)
        (define-key map [remap insert-buffer] 'ido-insert-buffer)
        (define-key map [remap kill-buffer] 'ido-kill-buffer)
-       (define-key map [remap display-buffer] 'ido-display-buffer)))))
+       (define-key map [remap display-buffer] 'ido-display-buffer))
+
+      (if ido-minor-mode-map-entry
+         (setcdr ido-minor-mode-map-entry map)
+       (setq ido-minor-mode-map-entry (cons 'ido-mode map))
+       (add-to-list 'minor-mode-map-alist ido-minor-mode-map-entry)))))
+
 
 (defun ido-everywhere (arg)
-  "Enable ido everywhere file and directory names are read."
+  "Toggle using ido speed-ups everywhere file and directory names are read.
+With ARG, turn ido speed-up on if arg is positive, off otherwise."
   (interactive "P")
   (setq ido-everywhere (if arg
                           (> (prefix-numeric-value arg) 0)
@@ -1383,12 +1520,11 @@ This function also adds a hook to the minibuffer."
 
 
 ;;; IDO KEYMAP
-(defun ido-define-mode-map ()
-  "Set up the keymap for `ido'."
-  (let (map)
-    ;; generated every time so that it can inherit new functions.
+(defun ido-init-completion-maps ()
+  "Set up the completion keymaps used by `ido'."
 
-    (setq map (copy-keymap minibuffer-local-map))
+  ;; Common map
+  (let ((map (make-sparse-keymap)))
     (define-key map "\C-a" 'ido-toggle-ignore)
     (define-key map "\C-c" 'ido-toggle-case)
     (define-key map "\C-e" 'ido-edit-input)
@@ -1402,63 +1538,98 @@ This function also adds a hook to the minibuffer."
     (define-key map "\C-t" 'ido-toggle-regexp)
     (define-key map "\C-z" 'ido-undo-merge-work-directory)
     (define-key map [(control ?\s)] 'ido-restrict-to-matches)
+    (define-key map [(meta ?\s)] 'ido-take-first-match)
     (define-key map [(control ?@)] 'ido-restrict-to-matches)
     (define-key map [right] 'ido-next-match)
     (define-key map [left] 'ido-prev-match)
     (define-key map "?" 'ido-completion-help)
-
     ;; Magic commands.
     (define-key map "\C-b" 'ido-magic-backward-char)
     (define-key map "\C-f" 'ido-magic-forward-char)
     (define-key map "\C-d" 'ido-magic-delete-char)
+    (set-keymap-parent map minibuffer-local-map)
+    (setq ido-common-completion-map map))
+
+  ;; File and directory map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "\C-x\C-b" 'ido-enter-switch-buffer)
+    (define-key map "\C-x\C-f" 'ido-fallback-command)
+    (define-key map "\C-x\C-d" 'ido-enter-dired)
+    (define-key map [down] 'ido-next-match-dir)
+    (define-key map [up]   'ido-prev-match-dir)
+    (define-key map [(meta up)] 'ido-prev-work-directory)
+    (define-key map [(meta down)] 'ido-next-work-directory)
+    (define-key map [backspace] 'ido-delete-backward-updir)
+    (define-key map "\d"        'ido-delete-backward-updir)
+    (define-key map [(meta backspace)] 'ido-delete-backward-word-updir)
+    (define-key map [(control backspace)] 'ido-up-directory)
+    (define-key map "\C-l" 'ido-reread-directory)
+    (define-key map [(meta ?d)] 'ido-wide-find-dir-or-delete-dir)
+    (define-key map [(meta ?b)] 'ido-push-dir)
+    (define-key map [(meta ?v)] 'ido-push-dir-first)
+    (define-key map [(meta ?f)] 'ido-wide-find-file-or-pop-dir)
+    (define-key map [(meta ?k)] 'ido-forget-work-directory)
+    (define-key map [(meta ?m)] 'ido-make-directory)
+    (define-key map [(meta ?n)] 'ido-next-work-directory)
+    (define-key map [(meta ?o)] 'ido-prev-work-file)
+    (define-key map [(meta control ?o)] 'ido-next-work-file)
+    (define-key map [(meta ?p)] 'ido-prev-work-directory)
+    (define-key map [(meta ?s)] 'ido-merge-work-directories)
+    (set-keymap-parent map ido-common-completion-map)
+    (setq ido-file-dir-completion-map map))
+
+  ;; File only map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "\C-k" 'ido-delete-file-at-head)
+    (define-key map "\C-o" 'ido-copy-current-word)
+    (define-key map "\C-w" 'ido-copy-current-file-name)
+    (define-key map [(meta ?l)] 'ido-toggle-literal)
+    (define-key map "\C-v" 'ido-toggle-vc)
+    (set-keymap-parent map ido-file-dir-completion-map)
+    (setq ido-file-completion-map map))
+
+  ;; Buffer map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "\C-x\C-f" 'ido-enter-find-file)
+    (define-key map "\C-x\C-b" 'ido-fallback-command)
+    (define-key map "\C-k" 'ido-kill-buffer-at-head)
+    (set-keymap-parent map ido-common-completion-map)
+    (setq ido-buffer-completion-map map)))
+
+
+(defun ido-setup-completion-map ()
+  "Set up the keymap for `ido'."
 
-    (when (memq ido-cur-item '(file dir))
-      (define-key map "\C-x\C-b" (or ido-context-switch-command 'ido-enter-switch-buffer))
-      (define-key map "\C-x\C-f" 'ido-fallback-command)
-      (define-key map "\C-x\C-d" (or (and ido-context-switch-command 'ignore) 'ido-enter-dired))
-      (define-key map [down] 'ido-next-match-dir)
-      (define-key map [up]   'ido-prev-match-dir)
-      (define-key map [(meta up)] 'ido-prev-work-directory)
-      (define-key map [(meta down)] 'ido-next-work-directory)
-      (define-key map [backspace] 'ido-delete-backward-updir)
-      (define-key map "\d"        'ido-delete-backward-updir)
-      (define-key map [(meta backspace)] 'ido-delete-backward-word-updir)
-      (define-key map [(control backspace)] 'ido-up-directory)
-      (define-key map "\C-l" 'ido-reread-directory)
-      (define-key map [(meta ?d)] 'ido-wide-find-dir-or-delete-dir)
-      (define-key map [(meta ?b)] 'ido-push-dir)
-      (define-key map [(meta ?f)] 'ido-wide-find-file-or-pop-dir)
-      (define-key map [(meta ?k)] 'ido-forget-work-directory)
-      (define-key map [(meta ?m)] 'ido-make-directory)
-      (define-key map [(meta ?n)] 'ido-next-work-directory)
-      (define-key map [(meta ?o)] 'ido-prev-work-file)
-      (define-key map [(meta control ?o)] 'ido-next-work-file)
-      (define-key map [(meta ?p)] 'ido-prev-work-directory)
-      (define-key map [(meta ?s)] 'ido-merge-work-directories)
-      )
+  ;; generated every time so that it can inherit new functions.
+  (let ((map (make-sparse-keymap))
+       (viper-p (if (boundp 'viper-mode) viper-mode)))
 
-    (when (eq ido-cur-item 'file)
-      (define-key map "\C-k" 'ido-delete-file-at-head)
-      (define-key map "\C-o" 'ido-copy-current-word)
-      (define-key map "\C-w" 'ido-copy-current-file-name)
-      (define-key map [(meta ?l)] 'ido-toggle-literal)
-      (define-key map "\C-v" 'ido-toggle-vc)
-      )
+    (when viper-p
+      (define-key map [remap viper-intercept-ESC-key] 'ignore))
 
-    (when (eq ido-cur-item 'buffer)
-      (define-key map "\C-x\C-f" (or ido-context-switch-command 'ido-enter-find-file))
-      (define-key map "\C-x\C-b" 'ido-fallback-command)
-      (define-key map "\C-k" 'ido-kill-buffer-at-head)
-      )
-
-    (when (if (boundp 'viper-mode) viper-mode)
-      (define-key map [remap viper-intercept-ESC-key] 'ignore)
-      (when (memq ido-cur-item '(file dir))
+    (cond
+     ((memq ido-cur-item '(file dir))
+      (when ido-context-switch-command
+       (define-key map "\C-x\C-b" ido-context-switch-command)
+       (define-key map "\C-x\C-d" 'ignore))
+      (when viper-p
        (define-key map [remap viper-backward-char] 'ido-delete-backward-updir)
        (define-key map [remap viper-del-backward-char-in-insert] 'ido-delete-backward-updir)
-       (define-key map [remap viper-delete-backward-word] 'ido-delete-backward-word-updir)))
+       (define-key map [remap viper-delete-backward-word] 'ido-delete-backward-word-updir))
+      (set-keymap-parent map
+                        (if (eq ido-cur-item 'file)
+                            ido-file-completion-map
+                          ido-file-dir-completion-map)))
+
+     ((eq ido-cur-item 'buffer)
+      (when ido-context-switch-command
+       (define-key map "\C-x\C-f" ido-context-switch-command))
+      (set-keymap-parent map ido-buffer-completion-map))
 
-    (setq ido-mode-map map)))
+     (t
+      (set-keymap-parent map ido-common-completion-map)))
+
+    (setq ido-completion-map map)))
 
 (defun ido-final-slash (dir &optional fix-it)
   ;; return DIR if DIR has final slash.
@@ -1484,6 +1655,7 @@ This function also adds a hook to the minibuffer."
   ;; connect on incomplete tramp paths (after entring just method:).
   (let ((ido-enable-tramp-completion nil))
     (and (ido-final-slash dir)
+        (not (ido-is-unc-host dir))
         (file-directory-p dir)
         (not (file-readable-p dir)))))
 
@@ -1494,18 +1666,34 @@ This function also adds a hook to the minibuffer."
   (let ((ido-enable-tramp-completion nil))
     (and (numberp ido-max-directory-size)
         (ido-final-slash dir)
+        (not (ido-is-unc-host dir))
         (file-directory-p dir)
         (> (nth 7 (file-attributes dir)) ido-max-directory-size))))
 
 (defun ido-set-current-directory (dir &optional subdir no-merge)
   ;; Set ido's current directory to DIR or DIR/SUBDIR
-  (setq dir (ido-final-slash dir t))
+  (unless (and ido-enable-tramp-completion
+              (string-match "\\`/[^/]*@\\'" dir))
+    (setq dir (ido-final-slash dir t)))
   (setq ido-use-merged-list nil
        ido-try-merged-list (not no-merge))
-  (if subdir
-      (setq dir (ido-final-slash (concat dir subdir) t)))
-  (if (equal dir ido-current-directory)
-      nil
+  (when subdir
+    (setq dir (concat dir subdir))
+    (unless (and ido-enable-tramp-completion
+                (string-match "\\`/[^/]*@\\'" dir))
+      (setq dir (ido-final-slash dir t))))
+  (if (get-buffer ido-completion-buffer)
+      (kill-buffer ido-completion-buffer))
+  (cond
+   ((equal dir ido-current-directory)
+    nil)
+   ((ido-is-unc-root dir)
+    (ido-trace "unc" dir)
+    (setq ido-current-directory dir)
+    (setq ido-directory-nonreadable nil)
+    (setq ido-directory-too-big nil)
+    t)
+   (t
     (ido-trace "cd" dir)
     (setq ido-current-directory dir)
     (if (get-buffer ido-completion-buffer)
@@ -1513,7 +1701,7 @@ This function also adds a hook to the minibuffer."
     (setq ido-directory-nonreadable (ido-nonreadable-directory-p dir))
     (setq ido-directory-too-big (and (not ido-directory-nonreadable)
                                     (ido-directory-too-big-p dir)))
-    t))
+    t)))
 
 (defun ido-set-current-home (&optional dir)
   ;; Set ido's current directory to user's home directory
@@ -1595,10 +1783,10 @@ This function also adds a hook to the minibuffer."
 ;;       the relevant function is called (find-file, write-file, etc).
 
 (defun ido-read-internal (item prompt history &optional default require-match initial)
-  "Perform the ido-read-buffer and ido-read-file-name functions.
+  "Perform the `ido-read-buffer' and `ido-read-file-name' functions.
 Return the name of a buffer or file selected.
 PROMPT is the prompt to give to the user.
-DEFAULT if given is the default directory to start with.
+DEFAULT if given is the default item to start with.
 If REQUIRE-MATCH is non-nil, an existing file must be selected.
 If INITIAL is non-nil, it specifies the initial input string."
   (let
@@ -1625,7 +1813,7 @@ If INITIAL is non-nil, it specifies the initial input string."
        (ido-enable-regexp ido-enable-regexp)
        )
 
-    (ido-define-mode-map)
+    (ido-setup-completion-map)
     (setq ido-text-init initial)
     (setq ido-input-stack nil)
 
@@ -1642,13 +1830,17 @@ If INITIAL is non-nil, it specifies the initial input string."
              (cond
               ((eq item 'buffer)
                (if (bufferp default) (buffer-name default) default))
-              ((stringp default) default)
+              ((stringp default)
+               (if (memq item '(file dir))
+                   (file-name-nondirectory default)
+                 default))
               ((eq item 'file)
                (and ido-enable-last-directory-history
                     (let ((d (assoc ido-current-directory ido-last-directory-list)))
                       (and d (cdr d)))))))
        (if (member ido-default-item ido-ignore-item-temp-list)
            (setq ido-default-item nil))
+       (ido-trace "new default" ido-default-item)
        (setq ido-set-default-item nil))
 
       (if ido-process-ignore-lists-inhibit
@@ -1730,7 +1922,8 @@ If INITIAL is non-nil, it specifies the initial input string."
       (if (and ido-matches (eq ido-try-merged-list 'auto))
          (setq ido-try-merged-list t))
       (let
-         ((minibuffer-local-completion-map ido-mode-map)
+         ((minibuffer-local-completion-map ido-completion-map)
+          (minibuffer-local-filename-completion-map ido-completion-map)
           (max-mini-window-height (or ido-max-window-height
                                       (and (boundp 'max-mini-window-height) max-mini-window-height)))
           (ido-completing-read t)
@@ -1883,6 +2076,7 @@ If INITIAL is non-nil, it specifies the initial input string."
              (setq ido-exit 'fallback
                    done t)
            (setq ido-set-default-item t)))
+
         ((or (string-match "[/\\][^/\\]" ido-selected)
              (and (memq system-type '(windows-nt ms-dos))
                   (string-match "\\`.:" ido-selected)))
@@ -1901,8 +2095,10 @@ If INITIAL is non-nil, it specifies the initial input string."
                        (cons (cons ido-current-directory ido-selected) ido-last-directory-list)))))
          (ido-set-current-directory ido-current-directory ido-selected)
          (if ido-input-stack
-             (while ido-input-stack
-               (let ((elt (car ido-input-stack)))
+             ; automatically pop stack elements which match existing files or directories
+             (let (elt)
+               (while (and (setq elt (car ido-input-stack))
+                           (file-exists-p (concat ido-current-directory (cdr elt))))
                  (if (setq ido-input-stack (cdr ido-input-stack))
                      (ido-set-current-directory ido-current-directory (cdr elt))
                    (setq ido-text-init (cdr elt)))
@@ -1916,7 +2112,7 @@ If INITIAL is non-nil, it specifies the initial input string."
 (defun ido-edit-input ()
   "Edit absolute file name entered so far with ido; terminate by RET."
   (interactive)
-  (setq ido-text-init ido-text)
+  (setq ido-text-init (if ido-matches (ido-name (car ido-matches)) ido-text))
   (setq ido-exit 'edit)
   (exit-minibuffer))
 
@@ -1959,7 +2155,10 @@ If INITIAL is non-nil, it specifies the initial input string."
        (if (eq method 'insert)
            (progn
              (ido-record-command 'insert-buffer buf)
-             (insert-buffer buf))
+             (push-mark
+              (save-excursion
+                (insert-buffer-substring (get-buffer buf))
+                (point))))
          (ido-visit-buffer buf method t)))
 
        ;; buffer doesn't exist
@@ -2025,7 +2224,6 @@ If INITIAL is non-nil, it specifies the initial input string."
   (let ((ido-current-directory (ido-expand-directory default))
        (ido-context-switch-command switch-cmd)
        ido-directory-nonreadable ido-directory-too-big
-       (minibuffer-completing-file-name t)
        filename)
 
     (if (or (not ido-mode) (ido-is-slow-ftp-host))
@@ -2069,9 +2267,10 @@ If INITIAL is non-nil, it specifies the initial input string."
 
       (unless filename
        (setq ido-saved-vc-hb vc-handled-backends)
-       (setq filename (ido-read-internal item
-                                         (or prompt "Find file: ")
-                                         'ido-file-history nil nil initial)))
+       (let ((minibuffer-completing-file-name t))
+         (setq filename (ido-read-internal item
+                                           (or prompt "Find file: ")
+                                           'ido-file-history nil nil initial))))
 
       ;; Choose the file name: either the text typed in, or the head
       ;; of the list of matches
@@ -2128,7 +2327,7 @@ If INITIAL is non-nil, it specifies the initial input string."
              (ido-record-command method dirname)
              (ido-record-work-directory)
              (funcall method dirname))
-            ((y-or-n-p (format "Directory %s does not exist. Create it " filename))
+            ((y-or-n-p (format "Directory %s does not exist. Create it? " filename))
              (ido-record-command method dirname)
              (ido-record-work-directory dirname)
              (make-directory-internal dirname)
@@ -2143,7 +2342,7 @@ If INITIAL is non-nil, it specifies the initial input string."
        (setq default-directory ido-current-directory)
        (ido-record-command 'write-file (concat ido-current-directory filename))
        (ido-record-work-directory)
-       (write-file filename))
+       (write-file (concat ido-current-directory filename)))
 
        ((eq method 'read-only)
        (ido-record-work-file filename)
@@ -2160,9 +2359,10 @@ If INITIAL is non-nil, it specifies the initial input string."
         (if ido-find-literal 'insert-file-literally 'insert-file)
         filename)
        (ido-record-work-directory)
-       (if ido-find-literal
-           (insert-file-contents-literally filename)
-         (insert-file-contents filename)))
+       (insert-file-1 filename
+                      (if ido-find-literal
+                          #'insert-file-contents-literally
+                        #'insert-file-contents)))
 
        (filename
        (ido-record-work-file filename)
@@ -2226,13 +2426,13 @@ If INITIAL is non-nil, it specifies the initial input string."
      ((and (= 1 (length ido-matches))
           (not (and ido-enable-tramp-completion
                     (string-equal ido-current-directory "/")
-                    (string-match "..[@:]\\'" (car ido-matches)))))
+                    (string-match "..[@:]\\'" (ido-name (car ido-matches))))))
       ;; only one choice, so select it.
       (if (not ido-confirm-unique-completion)
          (exit-minibuffer)
        (setq ido-rescan (not ido-enable-prefix))
        (delete-region (minibuffer-prompt-end) (point))
-       (insert (car ido-matches))))
+       (insert (ido-name (car ido-matches)))))
 
      (t ;; else there could be some completions
       (setq res ido-common-match-string)
@@ -2413,7 +2613,9 @@ timestamp has not changed (e.g. with ftp or on Windows)."
   (interactive)
   (if (and ido-mode (eq ido-cur-item 'file))
       (progn
-       (ido-remove-cached-dir ido-current-directory)
+       (if (ido-is-unc-root)
+           (setq ido-unc-hosts-cache t)
+         (ido-remove-cached-dir ido-current-directory))
        (setq ido-text-init ido-text)
        (setq ido-rotate-temp t)
        (setq ido-exit 'refresh)
@@ -2608,12 +2810,28 @@ If input stack is non-empty, delete current directory component."
       (ido-delete-backward-word-updir 1)
     (ido-wide-find-dir)))
 
+(defun ido-take-first-match ()
+  "Use first matching item as input text."
+  (interactive)
+  (when ido-matches
+    (setq ido-text-init (ido-name (car ido-matches)))
+    (setq ido-exit 'refresh)
+    (exit-minibuffer)))
+
 (defun ido-push-dir ()
   "Move to previous directory in file name, push current input on stack."
   (interactive)
   (setq ido-exit 'push)
   (exit-minibuffer))
 
+(defun ido-push-dir-first ()
+  "Move to previous directory in file name, push first match on stack."
+  (interactive)
+  (if ido-matches
+      (setq ido-text (ido-name (car ido-matches))))
+  (setq ido-exit 'push)
+  (exit-minibuffer))
+
 (defun ido-pop-dir (arg)
   "Pop directory from input stack back to input.
 With \\[universal-argument], pop all element."
@@ -2678,11 +2896,13 @@ With \\[universal-argument], pop all element."
   "Insert file name of current buffer.
 If repeated, insert text from buffer instead."
   (interactive "P")
-  (let* ((bfname (buffer-file-name ido-entry-buffer))
+  (let* ((bfname (or (buffer-file-name ido-entry-buffer)
+                    (buffer-name ido-entry-buffer)))
         (name (and bfname (file-name-nondirectory bfname))))
     (when name
       (setq ido-text-init
            (if (or all
+                   (eq last-command this-command)
                    (not (equal (file-name-directory bfname) ido-current-directory))
                    (not (string-match "\\.[^.]*\\'" name)))
                name
@@ -2864,12 +3084,14 @@ for first matching file."
   (let ((oa (ido-file-extension-order a n))
        (ob (ido-file-extension-order b n)))
     (cond
-     ((= oa ob)
-      lessp)
      ((and oa ob)
-      (if lessp
-         (> oa ob)
-       (< oa ob)))
+      (cond
+       ((= oa ob)
+       lessp)
+       (lessp
+       (> oa ob))
+       (t
+       (< oa ob))))
      (oa
       (not lessp))
      (ob
@@ -2916,7 +3138,12 @@ for first matching file."
   (let ((filenames
         (split-string
          (shell-command-to-string
-          (concat "find " dir " -name \"" (if prefix "" "*") file "*\" -type " (if finddir "d" "f") " -print"))))
+          (concat "find "
+                  (shell-quote-argument dir)
+                  " -name "
+                  (shell-quote-argument
+                   (concat (if prefix "" "*") file "*"))
+                  " -type " (if finddir "d" "f") " -print"))))
        filename d f
        res)
     (while filenames
@@ -3012,11 +3239,10 @@ for first matching file."
   (let (res)
     (message "Searching for `%s'...." text)
     (condition-case nil
-       (unless (catch 'input-pending-p
-                 (let ((throw-on-input 'input-pending-p))
-                   (setq res (ido-make-merged-file-list-1 text auto wide))
-                   t))
-         (setq res 'input-pending-p))
+       (if (eq t (setq res
+                       (while-no-input
+                         (ido-make-merged-file-list-1 text auto wide))))
+           (setq res 'input-pending-p))
       (quit
        (setq res t
             ido-try-merged-list nil
@@ -3093,27 +3319,29 @@ for first matching file."
    ((ido-nonreadable-directory-p dir) '())
    ;; do not check (ido-directory-too-big-p dir) here.
    ;; Caller must have done that if necessary.
+
    ((and ido-enable-tramp-completion
-        (string-match "\\`/\\([^/:]+:\\([^/:@]+@\\)?\\)\\'" dir))
-
-    ;; Trick tramp's file-name-all-completions handler to DTRT, as it
-    ;; has some pretty obscure requirements.  This seems to work...
-    ;; /ftp:           => (f-n-a-c "/ftp:" "")
-    ;; /ftp:kfs:       => (f-n-a-c "" "/ftp:kfs:")
-    ;; /ftp:kfs@      => (f-n-a-c "ftp:kfs@" "/")
-    ;; /ftp:kfs@kfs:  => (f-n-a-c "" "/ftp:kfs@kfs:")
-    ;; Currently no attempt is made to handle multi: stuff.
-
-    (let* ((prefix (match-string 1 dir))
-          (user-flag (match-beginning 2))
-          (len (and prefix (length prefix)))
-          compl)
-      (if user-flag
-         (setq dir (substring dir 1)))
-      (require 'tramp nil t)
-      (ido-trace "tramp complete" dir)
-      (setq compl (file-name-all-completions dir (if user-flag "/" "")))
-      (if (> len 0)
+        (or (fboundp 'tramp-completion-mode)
+            (require 'tramp nil t))
+        (string-match "\\`/[^/]+[:@]\\'" dir))
+    ;; Strip method:user@host: part of tramp completions.
+    ;; Tramp completions do not include leading slash.
+    (let ((len (1- (length dir)))
+         (compl
+          (or (file-name-all-completions "" dir)
+              ;; work around bug in ange-ftp.
+              ;; /ftp:user@host: => nil
+              ;; /ftp:user@host:./ => ok
+              (and
+               (not (string= "/ftp:" dir))
+               (tramp-tramp-file-p dir)
+               (fboundp 'tramp-ftp-file-name-p)
+               (funcall 'tramp-ftp-file-name-p dir)
+               (string-match ":\\'" dir)
+               (file-name-all-completions "" (concat dir "./"))))))
+      (if (and compl
+              (> (length (car compl)) len)
+              (string= (substring (car compl) 0 len) (substring dir 1)))
          (mapcar (lambda (c) (substring c len)) compl)
        compl)))
    (t
@@ -3122,36 +3350,52 @@ for first matching file."
 (defun ido-file-name-all-completions (dir)
   ;; Return name of all files in DIR
   ;; Uses and updates ido-dir-file-cache
-  (if (and (numberp ido-max-dir-file-cache) (> ido-max-dir-file-cache 0)
-          (stringp dir) (> (length dir) 0)
-          (ido-may-cache-directory dir))
-      (let* ((cached (assoc dir ido-dir-file-cache))
+  (cond
+   ((ido-is-unc-root dir)
+    (mapcar
+     (lambda (host)
+       (if (string-match "/\\'" host) host (concat host "/")))
+     (ido-unc-hosts t)))
+   ((and (numberp ido-max-dir-file-cache) (> ido-max-dir-file-cache 0)
+        (stringp dir) (> (length dir) 0)
+        (ido-may-cache-directory dir))
+    (let* ((cached (assoc dir ido-dir-file-cache))
             (ctime (nth 1 cached))
             (ftp (ido-is-ftp-directory dir))
-            (attr (if ftp nil (file-attributes dir)))
+            (unc (ido-is-unc-host dir))
+            (attr (if (or ftp unc) nil (file-attributes dir)))
             (mtime (nth 5 attr))
             valid)
        (when cached        ; should we use the cached entry ?
-         (if ftp
-             (setq valid (and (eq (car ctime) 'ftp)
-                              (ido-cache-ftp-valid (cdr ctime))))
+         (cond
+          (ftp
+           (setq valid (and (eq (car ctime) 'ftp)
+                            (ido-cache-ftp-valid (cdr ctime)))))
+          (unc
+           (setq valid (and (eq (car ctime) 'unc)
+                            (ido-cache-unc-valid (cdr ctime)))))
+          (t
            (if attr
                (setq valid (and (= (car ctime) (car mtime))
-                                (= (car (cdr ctime)) (car (cdr mtime)))))))
-         (if (not valid)
-             (setq ido-dir-file-cache (delq cached ido-dir-file-cache)
-                   cached nil)))
+                                (= (car (cdr ctime)) (car (cdr mtime))))))))
+         (unless valid
+           (setq ido-dir-file-cache (delq cached ido-dir-file-cache)
+                 cached nil)))
        (unless cached
-         (if (and ftp (file-readable-p dir))
-             (setq mtime (cons 'ftp (ido-time-stamp))))
+         (cond
+          (unc
+           (setq mtime (cons 'unc (ido-time-stamp))))
+          ((and ftp (file-readable-p dir))
+           (setq mtime (cons 'ftp (ido-time-stamp)))))
          (if mtime
              (setq cached (cons dir (cons mtime (ido-file-name-all-completions-1 dir)))
                    ido-dir-file-cache (cons cached ido-dir-file-cache)))
          (if (> (length ido-dir-file-cache) ido-max-dir-file-cache)
              (setcdr (nthcdr (1- ido-max-dir-file-cache) ido-dir-file-cache) nil)))
        (and cached
-            (cdr (cdr cached))))
-    (ido-file-name-all-completions-1 dir)))
+            (cdr (cdr cached)))))
+   (t
+    (ido-file-name-all-completions-1 dir))))
 
 (defun ido-remove-cached-dir (dir)
   ;; Remove dir from ido-dir-file-cache
@@ -3165,7 +3409,8 @@ for first matching file."
 (defun ido-make-file-list-1 (dir &optional merged)
   ;; Return list of non-ignored files in DIR
   ;; If MERGED is non-nil, each file is cons'ed with DIR
-  (and (or (ido-is-tramp-root dir) (file-directory-p dir))
+  (and (or (ido-is-tramp-root dir) (ido-is-unc-root dir)
+          (file-directory-p dir))
        (delq nil
             (mapcar
              (lambda (name)
@@ -3184,13 +3429,14 @@ for first matching file."
                              (if ido-file-extensions-order
                                  #'ido-file-extension-lessp
                                #'ido-file-lessp)))
-    (let ((default-directory ido-current-directory))
-      (ido-to-end ;; move ftp hosts and visited files to end
-       (delq nil (mapcar
-                 (lambda (x) (if (or (string-match "..:\\'" x)
-                                     (and (not (ido-final-slash x))
-                                          (get-file-buffer x))) x))
-                 ido-temp-list))))
+    (unless (ido-is-tramp-root ido-current-directory)
+      (let ((default-directory ido-current-directory))
+       (ido-to-end ;; move ftp hosts and visited files to end
+        (delq nil (mapcar
+                   (lambda (x) (if (or (string-match "..:\\'" x)
+                                       (and (not (ido-final-slash x))
+                                            (get-file-buffer x))) x))
+                   ido-temp-list)))))
     (ido-to-end  ;; move . files to end
      (delq nil (mapcar
                (lambda (x) (if (string-equal (substring x 0 1) ".") x))
@@ -3290,37 +3536,40 @@ for first matching file."
   (let* ((case-fold-search  ido-case-fold)
         (slash (and (not ido-enable-prefix) (ido-final-slash ido-text)))
         (text (if slash (substring ido-text 0 -1) ido-text))
-        (rexq (concat (if ido-enable-regexp text (regexp-quote text)) (if slash ".*/" "")))
+        (rex0 (if ido-enable-regexp text (regexp-quote text)))
+        (rexq (concat rex0 (if slash ".*/" "")))
         (re (if ido-enable-prefix (concat "\\`" rexq) rexq))
-        (full-re (and do-full (not ido-enable-regexp) (not (string-match "\$\\'" re))
-                      (concat "\\`" re "\\'")))
+        (full-re (and do-full (not ido-enable-regexp) (not (string-match "\$\\'" rex0))
+                      (concat "\\`" rex0 (if slash "/" "") "\\'")))
+        (suffix-re (and do-full slash
+                        (not ido-enable-regexp) (not (string-match "\$\\'" rex0))
+                        (concat rex0 "/\\'")))
         (prefix-re (and full-re (not ido-enable-prefix)
                         (concat "\\`" rexq)))
         (non-prefix-dot (or (not ido-enable-dot-prefix)
                             (not ido-process-ignore-lists)
                             ido-enable-prefix
                             (= (length ido-text) 0)))
-
-        full-matches
-        prefix-matches
-        matches)
+        full-matches suffix-matches prefix-matches matches)
     (setq ido-incomplete-regexp nil)
     (condition-case error
         (mapcar
          (lambda (item)
            (let ((name (ido-name item)))
-             (if (and (or non-prefix-dot
-                          (if (= (aref ido-text 0) ?.)
-                              (= (aref name 0) ?.)
-                            (/= (aref name 0) ?.)))
-                      (string-match re name))
-                 (cond
-                  ((and full-re (string-match full-re name))
-                   (setq full-matches (cons item full-matches)))
-                  ((and prefix-re (string-match prefix-re name))
-                   (setq prefix-matches (cons item prefix-matches)))
-                  (t (setq matches (cons item matches))))))
-           t)
+            (if (and (or non-prefix-dot
+                         (if (= (aref ido-text 0) ?.)
+                             (= (aref name 0) ?.)
+                           (/= (aref name 0) ?.)))
+                     (string-match re name))
+                (cond
+                 ((and full-re (string-match full-re name))
+                  (setq full-matches (cons item full-matches)))
+                 ((and suffix-re (string-match suffix-re name))
+                  (setq suffix-matches (cons item suffix-matches)))
+                 ((and prefix-re (string-match prefix-re name))
+                  (setq prefix-matches (cons item prefix-matches)))
+                 (t (setq matches (cons item matches))))))
+          t)
          items)
       (invalid-regexp
        (setq ido-incomplete-regexp t
@@ -3328,10 +3577,15 @@ for first matching file."
              ;; special-case single match, and handle appropriately
              ;; elsewhere.
              matches (cdr error))))
-    (if prefix-matches
-       (setq matches (nconc prefix-matches matches)))
-    (if full-matches
-       (setq matches (nconc full-matches matches)))
+    (when prefix-matches
+      (ido-trace "prefix match" prefix-matches)
+      (setq matches (nconc prefix-matches matches)))
+    (when suffix-matches
+      (ido-trace "suffix match" (list text suffix-re suffix-matches))
+      (setq matches (nconc suffix-matches matches)))
+    (when full-matches
+      (ido-trace "full match" (list text full-re full-matches))
+      (setq matches (nconc full-matches matches)))
     (when (and (null matches)
               ido-enable-flex-matching
               (> (length ido-text) 1)
@@ -3359,38 +3613,37 @@ for first matching file."
   (or (member name ido-ignore-item-temp-list)
       (and
        ido-process-ignore-lists re-list
-       (let ((data       (match-data))
-            (ext-list   (and ignore-ext ido-ignore-extensions
+       (save-match-data
+        (let ((ext-list (and ignore-ext ido-ignore-extensions
                              completion-ignored-extensions))
-            ignorep nextstr
-            (flen (length name)) slen)
-        (while ext-list
-          (setq nextstr (car ext-list))
-          (if (cond
-               ((stringp nextstr)
-                (and (>= flen (setq slen (length nextstr)))
-                     (string-equal (substring name (- flen slen)) nextstr)))
-               ((fboundp nextstr) (funcall nextstr name))
-               (t nil))
-              (setq ignorep t
-                    ext-list nil
-                    re-list nil)
-            (setq ext-list (cdr ext-list))))
-        (while re-list
-          (setq nextstr (car re-list))
-          (if (cond
-               ((stringp nextstr) (string-match nextstr name))
-               ((fboundp nextstr) (funcall nextstr name))
-               (t nil))
-              (setq ignorep t
-                    re-list nil)
-            (setq re-list (cdr re-list))))
-        ;; return the result
-        (if ignorep
-            (setq ido-ignored-list (cons name ido-ignored-list)))
-        (set-match-data data)
-        ignorep))))
-
+              (case-fold-search ido-case-fold)
+              ignorep nextstr
+              (flen (length name)) slen)
+          (while ext-list
+            (setq nextstr (car ext-list))
+            (if (cond
+                 ((stringp nextstr)
+                  (and (>= flen (setq slen (length nextstr)))
+                       (string-equal (substring name (- flen slen)) nextstr)))
+                 ((functionp nextstr) (funcall nextstr name))
+                 (t nil))
+                (setq ignorep t
+                      ext-list nil
+                      re-list nil)
+              (setq ext-list (cdr ext-list))))
+          (while re-list
+            (setq nextstr (car re-list))
+            (if (cond
+                 ((stringp nextstr) (string-match nextstr name))
+                 ((functionp nextstr) (funcall nextstr name))
+                 (t nil))
+                (setq ignorep t
+                      re-list nil)
+              (setq re-list (cdr re-list))))
+          ;; return the result
+          (if ignorep
+              (setq ido-ignored-list (cons name ido-ignored-list)))
+          ignorep)))))
 
 ;; Private variable used by `ido-word-matching-substring'.
 (defvar ido-change-word-sub)
@@ -3499,7 +3752,7 @@ for first matching file."
   "Kill the buffer at the head of `ido-matches'."
   (interactive)
   (let ((enable-recursive-minibuffers t)
-       (buf (car ido-matches)))
+       (buf (ido-name (car ido-matches))))
     (when buf
       (kill-buffer buf)
       ;; Check if buffer still exists.
@@ -3514,14 +3767,14 @@ for first matching file."
   "Delete the file at the head of `ido-matches'."
   (interactive)
   (let ((enable-recursive-minibuffers t)
-       (file (car ido-matches)))
+       (file (ido-name (car ido-matches))))
     (if file
        (setq file (concat ido-current-directory file)))
     (when (and file
               (file-exists-p file)
               (not (file-directory-p file))
               (file-writable-p ido-current-directory)
-              (yes-or-no-p (concat "Delete " file " ")))
+              (yes-or-no-p (concat "Delete " file "? ")))
       (delete-file file)
       ;; Check if file still exists.
       (if (file-exists-p file)
@@ -3533,9 +3786,10 @@ for first matching file."
 
 ;;; VISIT CHOSEN BUFFER
 (defun ido-visit-buffer (buffer method &optional record)
-  "Visit file named FILE according to METHOD.
+  "Switch to BUFFER according to METHOD.
 Record command in `command-history' if optional RECORD is non-nil."
-
+  (if (bufferp buffer)
+      (setq buffer (buffer-name buffer)))
   (let (win newframe)
     (cond
      ((eq method 'kill)
@@ -3543,33 +3797,7 @@ Record command in `command-history' if optional RECORD is non-nil."
          (ido-record-command 'kill-buffer buffer))
       (kill-buffer buffer))
 
-     ((eq method 'samewindow)
-      (if record
-         (ido-record-command 'switch-to-buffer buffer))
-      (switch-to-buffer buffer))
-
-     ((memq method '(always-frame maybe-frame))
-      (cond
-       ((and window-system
-            (setq win (ido-window-buffer-p buffer))
-            (or (eq method 'always-frame)
-                (y-or-n-p "Jump to frame? ")))
-       (setq newframe (window-frame win))
-       (if (fboundp 'select-frame-set-input-focus)
-           (select-frame-set-input-focus newframe)
-         (raise-frame newframe)
-         (select-frame newframe)
-         (unless (featurep 'xemacs)
-           (set-mouse-position (selected-frame) (1- (frame-width)) 0)))
-       (select-window win))
-       (t
-       ;;  No buffer in other frames...
-       (if record
-           (ido-record-command 'switch-to-buffer buffer))
-       (switch-to-buffer buffer)
-       )))
-
-     ((eq method 'otherwindow)
+     ((eq method 'other-window)
       (if record
          (ido-record-command 'switch-to-buffer buffer))
       (switch-to-buffer-other-window buffer))
@@ -3577,14 +3805,29 @@ Record command in `command-history' if optional RECORD is non-nil."
      ((eq method 'display)
       (display-buffer buffer))
 
-     ((eq method 'otherframe)
+     ((eq method 'other-frame)
       (switch-to-buffer-other-frame buffer)
-      (unless (featurep 'xemacs)
-       (select-frame-set-input-focus (selected-frame)))
+      (select-frame-set-input-focus (selected-frame)))
+
+     ((and (memq method '(raise-frame maybe-frame))
+          window-system
+          (setq win (ido-buffer-window-other-frame buffer))
+          (or (eq method 'raise-frame)
+              (y-or-n-p "Jump to frame? ")))
+      (setq newframe (window-frame win))
+      (select-frame-set-input-focus newframe)
+      (select-window win))
+
+     ;; (eq method 'selected-window)
+     (t
+      ;;  No buffer in other frames...
+      (if record
+         (ido-record-command 'switch-to-buffer buffer))
+      (switch-to-buffer buffer)
       ))))
 
 
-(defun ido-window-buffer-p  (buffer)
+(defun ido-buffer-window-other-frame  (buffer)
   ;; Return window pointer if BUFFER is visible in another frame.
   ;; If BUFFER is visible in the current frame, return nil.
   (let ((blist (ido-get-buffers-in-frames 'current)))
@@ -3606,10 +3849,10 @@ default is to show it in the same window, unless it is already visible
 in another frame.
 
 As you type in a string, all of the buffers matching the string are
-displayed if substring-matching is used \(default). Look at
+displayed if substring-matching is used \(default).  Look at
 `ido-enable-prefix' and `ido-toggle-prefix'.  When you have found the
 buffer you want, it can then be selected.  As you type, most keys have
-their normal keybindings, except for the following: \\<ido-mode-map>
+their normal keybindings, except for the following: \\<ido-buffer-completion-map>
 
 RET Select the buffer at the front of the list of matches.  If the
 list is empty, possibly prompt to create new buffer.
@@ -3629,7 +3872,7 @@ in a separate window.
 \\[ido-toggle-prefix] Toggle between substring and prefix matching.
 \\[ido-toggle-case] Toggle case-sensitive searching of buffer names.
 \\[ido-completion-help] Show list of matching buffers in separate window.
-\\[ido-enter-find-file] Drop into ido-find-file.
+\\[ido-enter-find-file] Drop into `ido-find-file'.
 \\[ido-kill-buffer-at-head] Kill buffer at head of buffer list.
 \\[ido-toggle-ignore] Toggle ignoring buffers listed in `ido-ignore-buffers'."
   (interactive)
@@ -3641,7 +3884,7 @@ in a separate window.
 The buffer name is selected interactively by typing a substring.
 For details of keybindings, do `\\[describe-function] ido'."
   (interactive)
-  (ido-buffer-internal 'otherwindow 'switch-to-buffer-other-window))
+  (ido-buffer-internal 'other-window 'switch-to-buffer-other-window))
 
 ;;;###autoload
 (defun ido-display-buffer ()
@@ -3674,7 +3917,7 @@ The buffer name is selected interactively by typing a substring.
 For details of keybindings, do `\\[describe-function] ido'."
   (interactive)
   (if ido-mode
-      (ido-buffer-internal 'otherframe)
+      (ido-buffer-internal 'other-frame)
     (call-interactively 'switch-to-buffer-other-frame)))
 
 ;;;###autoload
@@ -3697,7 +3940,7 @@ type in a string, all of the filenames matching the string are displayed
 if substring-matching is used \(default).  Look at `ido-enable-prefix' and
 `ido-toggle-prefix'.  When you have found the filename you want, it can
 then be selected.  As you type, most keys have their normal keybindings,
-except for the following: \\<ido-mode-map>
+except for the following: \\<ido-file-completion-map>
 
 RET Select the file at the front of the list of matches.  If the
 list is empty, possibly prompt to create new file.
@@ -3716,7 +3959,7 @@ in a separate window.
 \\[ido-merge-work-directories] search for file in the work directory history.
 \\[ido-forget-work-directory] removes current directory from the work directory history.
 \\[ido-prev-work-file] or \\[ido-next-work-file] cycle through the work file history.
-\\[ido-wide-find-file] and \\[ido-wide-find-dir] prompts and uses find to locate files or directories.
+\\[ido-wide-find-file-or-pop-dir] and \\[ido-wide-find-dir-or-delete-dir] prompts and uses find to locate files or directories.
 \\[ido-make-directory] prompts for a directory to create in current directory.
 \\[ido-fallback-command] Fallback to non-ido version of current command.
 \\[ido-toggle-regexp] Toggle regexp searching.
@@ -3736,7 +3979,7 @@ in a separate window.
 The file name is selected interactively by typing a substring.
 For details of keybindings, do `\\[describe-function] ido-find-file'."
   (interactive)
-  (ido-file-internal 'otherwindow 'find-file-other-window))
+  (ido-file-internal 'other-window 'find-file-other-window))
 
 ;;;###autoload
 (defun ido-find-alternate-file ()
@@ -3784,7 +4027,7 @@ For details of keybindings, do `\\[describe-function] ido-find-file'."
 The file name is selected interactively by typing a substring.
 For details of keybindings, do `\\[describe-function] ido-find-file'."
   (interactive)
-  (ido-file-internal 'otherframe 'find-file-other-frame))
+  (ido-file-internal 'other-frame 'find-file-other-frame))
 
 ;;;###autoload
 (defun ido-write-file ()
@@ -3870,12 +4113,13 @@ For details of keybindings, do `\\[describe-function] ido-find-file'."
          try-single-dir-match
          refresh)
 
-      (ido-trace "\nexhibit" this-command)
-      (ido-trace "dir" ido-current-directory)
-      (ido-trace "contents" contents)
-      (ido-trace "list" ido-cur-list)
-      (ido-trace "matches" ido-matches)
-      (ido-trace "rescan" ido-rescan)
+      (when ido-trace-enable
+       (ido-trace "\nexhibit" this-command)
+       (ido-trace "dir" ido-current-directory)
+       (ido-trace "contents" contents)
+       (ido-trace "list" ido-cur-list)
+       (ido-trace "matches" ido-matches)
+       (ido-trace "rescan" ido-rescan))
 
       (save-excursion
        (goto-char (point-max))
@@ -3894,10 +4138,16 @@ For details of keybindings, do `\\[describe-function] ido-find-file'."
          )
 
         ((= (length contents) 1)
-         (when (and (ido-is-tramp-root) (string-equal contents "/"))
+         (cond
+          ((and (ido-is-tramp-root) (string-equal contents "/"))
            (ido-set-current-directory ido-current-directory contents)
            (setq refresh t))
-         )
+          ((and (ido-unc-hosts) (string-equal contents "/")
+                (let ((ido-enable-tramp-completion nil))
+                  (ido-is-root-directory)))
+           (ido-set-current-directory "//")
+           (setq refresh t))
+         ))
 
         ((and (string-match (if ido-enable-tramp-completion "..[:@]\\'" "..:\\'") contents)
               (ido-is-root-directory)) ;; Ange-ftp or tramp
@@ -3959,7 +4209,7 @@ For details of keybindings, do `\\[describe-function] ido-find-file'."
            ((= (length contents) 2)
             "/")
            (ido-matches
-            (concat ido-current-directory (car ido-matches)))
+            (concat ido-current-directory (ido-name (car ido-matches))))
            (t
             (concat ido-current-directory (substring contents 0 -1)))))
          (setq ido-text-init (substring contents -1))
@@ -3991,15 +4241,16 @@ For details of keybindings, do `\\[describe-function] ido-find-file'."
        (ido-set-matches)
        (ido-trace "new    " ido-matches)
 
-       (when (and ido-enter-single-matching-directory
+       (when (and ido-enter-matching-directory
                   ido-matches
-                  (null (cdr ido-matches))
-                  (ido-final-slash (car ido-matches))
+                  (or (eq ido-enter-matching-directory 'first)
+                      (null (cdr ido-matches)))
+                  (ido-final-slash (ido-name (car ido-matches)))
                   (or try-single-dir-match
-                      (eq ido-enter-single-matching-directory t)))
+                      (eq ido-enter-matching-directory t)))
          (ido-trace "single match" (car ido-matches))
          (ido-set-current-directory
-          (concat ido-current-directory (car ido-matches)))
+          (concat ido-current-directory (ido-name (car ido-matches))))
          (setq ido-exit 'refresh)
          (exit-minibuffer))
 
@@ -4259,6 +4510,8 @@ See `read-file-name' for additional parameters."
             (ido-directory-too-big (and (not ido-directory-nonreadable)
                                         (ido-directory-too-big-p ido-current-directory)))
             (ido-work-directory-index -1)
+            (ido-show-dot-for-dired (and ido-show-dot-for-dired
+                                         (not default-filename)))
             (ido-work-file-index -1)
             (ido-find-literal nil))
        (setq ido-exit nil)