diff lisp/minibuf.el @ 209:41ff10fd062f r20-4b3

Import from CVS: tag r20-4b3
author cvs
date Mon, 13 Aug 2007 10:04:58 +0200
parents
children 1f0dabaa0855
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/minibuf.el	Mon Aug 13 10:04:58 2007 +0200
@@ -0,0 +1,2112 @@
+;;; minibuf.el --- Minibuffer functions for XEmacs
+
+;; Copyright (C) 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1995 Tinker Systems
+;; Copyright (C) 1995, 1996 Ben Wing
+ 
+;; Author: Richard Mlynarik
+;; Created: 2-Oct-92
+;; Maintainer: XEmacs Development Team
+;; Keywords: internal, dumped
+
+;; This file is part of XEmacs.
+
+;; XEmacs 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.
+
+;; XEmacs 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 XEmacs; see the file COPYING.  If not, write to the 
+;; Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Synched up with: all the minibuffer history stuff is synched with
+;;; 19.30.  Not sure about the rest.
+
+;;; Commentary:
+
+;; This file is dumped with XEmacs.
+
+;; Written by Richard Mlynarik 2-Oct-92
+
+;; 06/11/1997 -  Use char-(after|before) instead of
+;;  (following|preceding)-char. -slb
+
+;;; Code:
+
+(defgroup minibuffer nil
+  "Minibuffer customizations"
+  :group 'environment)
+
+
+(defcustom insert-default-directory t
+ "*Non-nil means when reading a filename start with default dir in minibuffer."
+ :type 'boolean
+ :group 'minibuffer)
+
+(defcustom minibuffer-history-uniquify t
+  "*Non-nil means when adding an item to a minibuffer history, remove
+previous occurances of the same item from the history list first,
+rather than just consing the new element onto the front of the list."
+  :type 'boolean
+  :group 'minibuffer)
+
+(defvar minibuffer-completion-table nil
+  "Alist or obarray used for completion in the minibuffer.
+This becomes the ALIST argument to `try-completion' and `all-completions'.
+
+The value may alternatively be a function, which is given three arguments:
+  STRING, the current buffer contents;
+  PREDICATE, the predicate for filtering possible matches;
+  CODE, which says what kind of things to do.
+CODE can be nil, t or `lambda'.
+nil means to return the best completion of STRING, nil if there is none,
+  or t if it is was already a unique completion.
+t means to return a list of all possible completions of STRING.
+`lambda' means to return t if STRING is a valid completion as it stands.")
+
+(defvar minibuffer-completion-predicate nil
+  "Within call to `completing-read', this holds the PREDICATE argument.")
+
+(defvar minibuffer-completion-confirm nil
+  "Non-nil => demand confirmation of completion before exiting minibuffer.")
+
+(defvar minibuffer-confirm-incomplete nil
+  "If true, then in contexts where completing-read allows answers which
+are not valid completions, an extra RET must be typed to confirm the
+response.  This is helpful for catching typos, etc.")
+
+(defcustom completion-auto-help t
+  "*Non-nil means automatically provide help for invalid completion input."
+  :type 'boolean
+  :group 'minibuffer)
+
+(defcustom enable-recursive-minibuffers nil
+  "*Non-nil means to allow minibuffer commands while in the minibuffer.
+More precisely, this variable makes a difference when the minibuffer window
+is the selected window.  If you are in some other window, minibuffer commands
+are allowed even if a minibuffer is active."
+  :type 'boolean
+  :group 'minibuffer)
+
+(defcustom minibuffer-max-depth 1
+  ;; See comment in #'minibuffer-max-depth-exceeded
+  "*Global maximum number of minibuffers allowed;
+compare to enable-recursive-minibuffers, which is only consulted when the
+minibuffer is reinvoked while it is the selected window."
+  :type '(choice integer
+		 (const :tag "Indefinite" nil))
+  :group 'minibuffer)
+
+;; Moved to C.  The minibuffer prompt must be setup before this is run
+;; and that can only be done from the C side.
+;(defvar minibuffer-setup-hook nil
+;  "Normal hook run just after entry to minibuffer.")
+
+(defvar minibuffer-exit-hook nil
+  "Normal hook run just after exit from minibuffer.")
+
+(defvar minibuffer-help-form nil
+  "Value that `help-form' takes on inside the minibuffer.")
+
+(defvar minibuffer-local-map
+  (let ((map (make-sparse-keymap 'minibuffer-local-map)))
+    map)
+  "Default keymap to use when reading from the minibuffer.")
+
+(defvar minibuffer-local-completion-map
+  (let ((map (make-sparse-keymap 'minibuffer-local-completion-map)))
+    (set-keymap-parents map (list minibuffer-local-map))
+    map)
+  "Local keymap for minibuffer input with completion.")
+
+(defvar minibuffer-local-must-match-map
+  (let ((map (make-sparse-keymap 'minibuffer-must-match-map)))
+    (set-keymap-parents map (list minibuffer-local-completion-map))
+    map)
+  "Local keymap for minibuffer input with completion, for exact match.")
+
+;; (define-key minibuffer-local-map "\C-g" 'abort-recursive-edit)
+(define-key minibuffer-local-map "\C-g" 'minibuffer-keyboard-quit) ;; moved here from pending-del.el
+(define-key minibuffer-local-map "\r" 'exit-minibuffer)
+(define-key minibuffer-local-map "\n" 'exit-minibuffer)
+
+;; Historical crock.  Unused by anything but user code, if even that
+;(defvar minibuffer-local-ns-map
+;  (let ((map (make-sparse-keymap 'minibuffer-local-ns-map)))
+;    (set-keymap-parents map (list minibuffer-local-map))
+;    map)
+;  "Local keymap for the minibuffer when spaces are not allowed.")
+;(define-key minibuffer-local-ns-map [space] 'exit-minibuffer)
+;(define-key minibuffer-local-ns-map [tab] 'exit-minibuffer)
+;(define-key minibuffer-local-ns-map [?\?] 'self-insert-and-exit)
+
+(define-key minibuffer-local-completion-map "\t" 'minibuffer-complete)
+(define-key minibuffer-local-completion-map " " 'minibuffer-complete-word)
+(define-key minibuffer-local-completion-map "?" 'minibuffer-completion-help)
+(define-key minibuffer-local-must-match-map "\r" 'minibuffer-complete-and-exit)
+(define-key minibuffer-local-must-match-map "\n" 'minibuffer-complete-and-exit)
+
+(define-key minibuffer-local-map "\M-n" 'next-history-element)
+(define-key minibuffer-local-map "\M-p" 'previous-history-element)
+(define-key minibuffer-local-map '[next]  "\M-n")
+(define-key minibuffer-local-map '[prior] "\M-p")
+(define-key minibuffer-local-map "\M-r" 'previous-matching-history-element)
+(define-key minibuffer-local-map "\M-s" 'next-matching-history-element)
+(define-key minibuffer-local-must-match-map [next] 
+  'next-complete-history-element)
+(define-key minibuffer-local-must-match-map [prior]
+  'previous-complete-history-element)
+
+;; This is an experiment--make up and down arrows do history.
+(define-key minibuffer-local-map [up] 'previous-history-element)
+(define-key minibuffer-local-map [down] 'next-history-element)
+(define-key minibuffer-local-completion-map [up] 'previous-history-element)
+(define-key minibuffer-local-completion-map [down] 'next-history-element)
+(define-key minibuffer-local-must-match-map [up] 'previous-history-element)
+(define-key minibuffer-local-must-match-map [down] 'next-history-element)
+
+(defvar read-expression-map (let ((map (make-sparse-keymap
+					'read-expression-map)))
+                              (set-keymap-parents map
+						  (list minibuffer-local-map))
+                              (define-key map "\M-\t" 'lisp-complete-symbol)
+                              map)
+  "Minibuffer keymap used for reading Lisp expressions.")
+
+(defvar read-shell-command-map
+  (let ((map (make-sparse-keymap 'read-shell-command-map)))
+    (set-keymap-parents map (list minibuffer-local-map))
+    (define-key map "\t" 'comint-dynamic-complete)
+    (define-key map "\M-\t" 'comint-dynamic-complete)
+    (define-key map "\M-?" 'comint-dynamic-list-completions)
+    map)
+  "Minibuffer keymap used by shell-command and related commands.")
+
+(defcustom use-dialog-box t
+  "*Variable controlling usage of the dialog box.
+If nil, the dialog box will never be used, even in response to mouse events."
+  :type 'boolean
+  :group 'minibuffer)
+
+(defcustom minibuffer-electric-file-name-behavior t
+  "*If non-nil, slash and tilde in certain places cause immediate deletion.
+These are the same places where this behavior would occur later on anyway,
+in `substitute-in-file-name'."
+  :type 'boolean
+  :group 'minibuffer)
+
+(defun minibuffer-electric-slash ()
+  ;; by Stig@hackvan.com
+  (interactive)
+  (and minibuffer-electric-file-name-behavior
+       (eq ?/ (char-before (point)))
+       (not (save-excursion
+	      (goto-char (point-min))
+	      (and (looking-at "^/.+:~?")
+		   (re-search-forward "^/.+:~?[^/]*" nil t)
+		   (progn
+		     (delete-region (point) (point-max))
+		     t))))
+       (not (eq (point) (1+ (point-min)))) ; permit `//hostname/path/to/file'
+       (not (eq ?: (char-after (- (point) 2)))) ; permit `http://url/goes/here'
+       (delete-region (point-min) (point)))
+  (insert ?/))
+
+(defun minibuffer-electric-tilde ()
+  (interactive)
+  (and minibuffer-electric-file-name-behavior
+       (eq ?/ (char-before (point)))
+       ;; permit URL's with //, for e.g. http://hostname/~user
+       (not (save-excursion (search-backward "//" nil t)))
+       (delete-region (point-min) (point)))
+  (insert ?~))
+
+(defvar read-file-name-map
+  (let ((map (make-sparse-keymap 'read-file-name-map)))
+    (set-keymap-parents map (list minibuffer-local-completion-map))
+    (define-key map "/" 'minibuffer-electric-slash)
+    (define-key map "~" 'minibuffer-electric-tilde)
+    map
+    ))
+
+(defvar read-file-name-must-match-map
+  (let ((map (make-sparse-keymap 'read-file-name-map)))
+    (set-keymap-parents map (list minibuffer-local-must-match-map))
+    (define-key map "/" 'minibuffer-electric-slash)
+    (define-key map "~" 'minibuffer-electric-tilde)
+    map
+    ))
+
+(defun minibuffer-keyboard-quit ()
+  "Abort recursive edit.
+If `zmacs-regions' is true, and the zmacs region is active in this buffer,
+then this key deactivates the region without beeping."
+  (interactive)
+  (if (and (region-active-p)
+	   (eq (current-buffer) (zmacs-region-buffer)))
+      ;; pseudo-zmacs compatibility: don't beep if this ^G is simply
+      ;; deactivating the region.  If it is inactive, beep.
+      nil
+    (abort-recursive-edit)))
+
+;;;; Guts of minibuffer invocation
+
+;;#### The only things remaining in C are
+;; "Vminibuf_prompt" and the display junk
+;;  "minibuf_prompt_width" and "minibuf_prompt_pix_width"
+;; Also "active_frame", though I suspect I could already
+;;   hack that in Lisp if I could make any sense of the
+;;   complete mess of frame/frame code in XEmacs.
+;; Vminibuf_prompt could easily be made Lisp-bindable.
+;;  I suspect that minibuf_prompt*_width are actually recomputed
+;;  by redisplay as needed -- or could be arranged to be so --
+;;  and that there could be need for read-minibuffer-internal to
+;;  save and restore them.
+;;#### The only other thing which read-from-minibuffer-internal does
+;;  which we can't presently do in Lisp is move the frame cursor
+;;  to the start of the minibuffer line as it returns.  This is
+;;  a rather nice touch and should be preserved -- probably by
+;;  providing some Lisp-level mechanism (extension to cursor-in-echo-area ?)
+;;  to effect it.
+
+
+;; Like reset_buffer in FSF's buffer.c
+;;  (Except that kill-all-local-variables doesn't nuke 'permanent-local
+;;   variables -- we preserve them, reset_buffer doesn't.)
+(defun reset-buffer (buffer)
+  (with-current-buffer buffer
+    ;(if (fboundp 'unlock-buffer) (unlock-buffer))
+    (kill-all-local-variables)
+    (setq buffer-read-only nil)
+    (erase-buffer)
+    ;(setq default-directory nil)
+    (setq buffer-file-name nil)
+    (setq buffer-file-truename nil)
+    (set-buffer-modified-p nil)
+    (setq buffer-backed-up nil)
+    (setq buffer-auto-save-file-name nil)
+    (set-buffer-dedicated-frame buffer nil)
+    buffer))
+
+(defvar minibuffer-history-variable 'minibuffer-history
+  "History list symbol to add minibuffer values to.
+Each minibuffer output is added with
+  (set minibuffer-history-variable
+       (cons STRING (symbol-value minibuffer-history-variable)))")
+(defvar minibuffer-history-position)
+
+;; Added by hniksic:
+(defvar initial-minibuffer-history-position)
+(defvar current-minibuffer-contents)
+(defvar current-minibuffer-point)
+
+(defcustom minibuffer-history-minimum-string-length 3
+  "*If this variable is non-nil, a string will not be added to the
+minibuffer history if its length is less than that value."
+  :type '(choice (const :tag "Any" nil)
+		 integer)
+  :group 'minibuffer)
+
+(define-error 'input-error "Keyboard input error")
+
+(put 'input-error 'display-error
+     #'(lambda (error-object stream)
+	 (princ (cadr error-object) stream)))
+
+(defun read-from-minibuffer (prompt &optional initial-contents
+                                    keymap
+                                    readp
+                                    history
+				    abbrev-table)
+  "Read a string from the minibuffer, prompting with string PROMPT.
+If optional second arg INITIAL-CONTENTS is non-nil, it is a string
+  to be inserted into the minibuffer before reading input.
+  If INITIAL-CONTENTS is (STRING . POSITION), the initial input
+  is STRING, but point is placed POSITION characters into the string.
+Third arg KEYMAP is a keymap to use whilst reading;
+  if omitted or nil, the default is `minibuffer-local-map'.
+If fourth arg READ is non-nil, then interpret the result as a lisp object
+  and return that object:
+  in other words, do `(car (read-from-string INPUT-STRING))'
+Fifth arg HISTORY, if non-nil, specifies a history list
+  and optionally the initial position in the list.
+  It can be a symbol, which is the history list variable to use,
+  or it can be a cons cell (HISTVAR . HISTPOS).
+  In that case, HISTVAR is the history list variable to use,
+  and HISTPOS is the initial position (the position in the list
+  which INITIAL-CONTENTS corresponds to).
+  If HISTORY is `t', no history will be recorded.
+  Positions are counted starting from 1 at the beginning of the list.
+Sixth arg ABBREV-TABLE, if non-nil, becomes the value of `local-abbrev-table'
+  in the minibuffer.
+
+See also the variable completion-highlight-first-word-only for control over
+  completion display."
+  (if (and (not enable-recursive-minibuffers)
+           (> (minibuffer-depth) 0)
+           (eq (selected-window) (minibuffer-window)))
+      (error "Command attempted to use minibuffer while in minibuffer"))
+
+  (if (and minibuffer-max-depth
+	   (> minibuffer-max-depth 0)
+           (>= (minibuffer-depth) minibuffer-max-depth))
+      (minibuffer-max-depth-exceeded))
+
+  ;; catch this error before the poor user has typed something...
+  (if history
+      (if (symbolp history)
+	  (or (boundp history)
+	      (error "History list %S is unbound" history))
+	(or (boundp (car history))
+	    (error "History list %S is unbound" (car history)))))
+
+  (if (noninteractive)
+      (progn
+        ;; XEmacs in -batch mode calls minibuffer: print the prompt.
+        (message "%s" (gettext prompt))
+        ;;#### force-output
+
+        ;;#### Should this even be falling though to the code below?
+        ;;#### How does this stuff work now, anyway?
+        ))
+  (let* ((dir default-directory)
+         (owindow (selected-window))
+	 (oframe (selected-frame))
+         (window (minibuffer-window))
+         (buffer (if (eq (minibuffer-depth) 0)
+                     (window-buffer window)
+		   (get-buffer-create (format " *Minibuf-%d"
+					      (minibuffer-depth)))))
+         (frame (window-frame window))
+         (mconfig (if (eq frame (selected-frame)) 
+                      nil (current-window-configuration frame)))
+         (oconfig (current-window-configuration))
+	 ;; dynamic scope sucks sucks sucks sucks sucks sucks.
+	 ;; `M-x doctor' makes history a local variable, and thus
+	 ;; our binding above is buffer-local and doesn't apply
+	 ;; once we switch buffers!!!!  We demand better scope!
+	 (_history_ history))
+    (unwind-protect
+         (progn
+           (set-buffer (reset-buffer buffer))
+           (setq default-directory dir)
+           (make-local-variable 'print-escape-newlines)
+           (setq print-escape-newlines t)
+	   (make-local-variable 'current-minibuffer-contents)
+	   (make-local-variable 'current-minibuffer-point)
+	   (make-local-variable 'initial-minibuffer-history-position)
+	   (setq current-minibuffer-contents ""
+		 current-minibuffer-point 1)
+	   (if (not minibuffer-smart-completion-tracking-behavior)
+	       nil
+	     (make-local-variable 'mode-motion-hook)
+	     (or mode-motion-hook
+		 ;;####disgusting
+		 (setq mode-motion-hook 'minibuffer-smart-mouse-tracker))
+	     (make-local-variable 'mouse-track-click-hook)
+	     (add-hook 'mouse-track-click-hook
+		       'minibuffer-smart-maybe-select-highlighted-completion))
+           (set-window-buffer window buffer)
+           (select-window window)
+           (set-window-hscroll window 0)
+           (buffer-enable-undo buffer)
+           (message nil)
+           (if initial-contents
+               (if (consp initial-contents)
+                   (progn
+                     (insert (car initial-contents))
+                     (goto-char (1+ (cdr initial-contents)))
+		     (setq current-minibuffer-contents (car initial-contents)
+			   current-minibuffer-point (cdr initial-contents)))
+		 (insert initial-contents)
+		 (setq current-minibuffer-contents initial-contents
+		       current-minibuffer-point (point))))
+           (use-local-map (or keymap minibuffer-local-map))
+           (let ((mouse-grabbed-buffer
+		  (and minibuffer-smart-completion-tracking-behavior
+		       (current-buffer)))
+                 (current-prefix-arg current-prefix-arg)
+                 (help-form minibuffer-help-form)
+                 (minibuffer-history-variable (cond ((not _history_)
+                                                     'minibuffer-history)
+                                                    ((consp _history_)
+                                                     (car _history_))
+                                                    (t
+                                                     _history_)))
+                 (minibuffer-history-position (cond ((consp _history_)
+                                                     (cdr _history_))
+                                                    (t
+                                                     0)))
+                 (minibuffer-scroll-window owindow))
+	     (setq initial-minibuffer-history-position
+		   minibuffer-history-position)
+	     (if abbrev-table
+		 (setq local-abbrev-table abbrev-table
+		       abbrev-mode t))
+	     ;; This is now run from read-minibuffer-internal
+             ;(if minibuffer-setup-hook
+             ;    (run-hooks 'minibuffer-setup-hook))
+             ;(message nil)
+             (if (eq 't
+                     (catch 'exit
+                       (if (> (recursion-depth) (minibuffer-depth))
+                           (let ((standard-output t)
+                                 (standard-input t))
+                             (read-minibuffer-internal prompt))
+                           (read-minibuffer-internal prompt))))
+                 ;; Translate an "abort" (throw 'exit 't)
+                 ;;  into a real quit
+                 (signal 'quit '())
+               ;; return value
+               (let* ((val (progn (set-buffer buffer)
+                                  (if minibuffer-exit-hook
+                                      (run-hooks 'minibuffer-exit-hook))
+                                  (buffer-string)))
+                    (histval val)
+                      (err nil))
+                 (if readp
+                     (condition-case e
+                         (let ((v (read-from-string val)))
+                           (if (< (cdr v) (length val))
+                               (save-match-data
+                                 (or (string-match "[ \t\n]*\\'" val (cdr v))
+                                     (error "Trailing garbage following expression"))))
+                           (setq v (car v))
+                           ;; total total kludge
+                           (if (stringp v) (setq v (list 'quote v)))
+                           (setq val v))
+                       (end-of-file
+			(setq err
+			      '(input-error "End of input before end of expression")))
+		       (error (setq err e))))
+                 ;; Add the value to the appropriate history list unless
+                 ;; it's already the most recent element, or it's only
+                 ;; two characters long.
+                 (if (and (symbolp minibuffer-history-variable)
+                          (boundp minibuffer-history-variable))
+		     (let ((list (symbol-value minibuffer-history-variable)))
+		       (or (eq list t)
+			   (null val)
+			   (and list (equal histval (car list)))
+			   (and (stringp val)
+				minibuffer-history-minimum-string-length
+				(< (length val)
+				   minibuffer-history-minimum-string-length))
+			   (set minibuffer-history-variable
+				(if minibuffer-history-uniquify
+				    (cons histval (remove histval list))
+				  (cons histval list))))))
+                 (if err (signal (car err) (cdr err)))
+                 val))))
+      ;; stupid display code requires this for some reason
+      (set-buffer buffer)
+      (buffer-disable-undo buffer)
+      (setq buffer-read-only nil)
+      (erase-buffer)
+
+      ;; restore frame configurations
+      (if (and mconfig (frame-live-p oframe)
+	       (eq frame (selected-frame)))
+	  ;; if we changed frames (due to surrogate minibuffer),
+	  ;; and we're still on the new frame, go back to the old one.
+	  (select-frame oframe))
+      (if mconfig (set-window-configuration mconfig))
+      (set-window-configuration oconfig))))
+
+
+(defun minibuffer-max-depth-exceeded ()
+  ;;
+  ;; This signals an error if an Nth minibuffer is invoked while N-1 are
+  ;; already active, whether the minibuffer window is selected or not.
+  ;; Since, under X, it's easy to jump out of the minibuffer (by doing M-x,
+  ;; getting distracted, and clicking elsewhere) many many novice users have
+  ;; had the problem of having multiple minibuffers build up, even to the
+  ;; point of exceeding max-lisp-eval-depth.  Since the variable
+  ;; enable-recursive-minibuffers historically/crockishly is only consulted
+  ;; when the minibuffer is currently active (like typing M-x M-x) it doesn't
+  ;; help in this situation.
+  ;;
+  ;; This routine also offers to edit .emacs for you to get rid of this
+  ;; complaint, like `disabled' commands do, since it's likely that non-novice
+  ;; users will be annoyed by this change, so we give them an easy way to get
+  ;; rid of it forever.
+  ;; 
+  (beep t 'minibuffer-limit-exceeded)
+  (message
+   "Minibuffer already active: abort it with `^]', enable new one with `n': ")
+  (let ((char (let ((cursor-in-echo-area t)) ; #### doesn't always work??
+		(read-char))))
+    (cond
+     ((eq char ?n)
+      (cond
+       ((y-or-n-p "Enable recursive minibuffers for other sessions too? ")
+	;; This is completely disgusting, but it's basically what novice.el
+	;; does.  This kind of thing should be generalized.
+	(setq minibuffer-max-depth nil)
+	(save-excursion
+	  (set-buffer
+	   (find-file-noselect
+	    (substitute-in-file-name custom-file)))
+	  (goto-char (point-min))
+	  (if (re-search-forward 
+	       "^(setq minibuffer-max-depth \\([0-9]+\\|'?nil\\|'?()\\))\n"
+	       nil t)
+	      (delete-region (match-beginning 0 ) (match-end 0))
+	    ;; Must have been disabled by default.
+	    (goto-char (point-max)))
+	  (insert"\n(setq minibuffer-max-depth nil)\n")
+	  (save-buffer))
+	(message "Multiple minibuffers enabled")
+	(sit-for 1))))
+     ((eq char ?)
+      (abort-recursive-edit))
+     (t
+      (error "Minibuffer already active")))))
+
+
+;;;; Guts of minibuffer completion
+
+
+;; Used by minibuffer-do-completion
+(defvar last-exact-completion)
+
+(defun temp-minibuffer-message (m)
+  (let ((savemax (point-max)))
+    (save-excursion
+      (goto-char (point-max))
+      (message nil)
+      (insert m))
+    (let ((inhibit-quit t))
+      (sit-for 2)
+      (delete-region savemax (point-max))
+      ;;  If the user types a ^G while we're in sit-for, then quit-flag 
+      ;;  gets set. In this case, we want that ^G to be interpreted 
+      ;;  as a normal character, and act just like typeahead.
+      (if (and quit-flag (not unread-command-event))
+          (setq unread-command-event (character-to-event (quit-char))
+                quit-flag nil)))))
+
+
+;; Determines whether buffer-string is an exact completion
+(defun exact-minibuffer-completion-p (buffer-string)
+  (cond ((not minibuffer-completion-table)
+         ;; Empty alist
+         nil)
+        ((vectorp minibuffer-completion-table)
+         (let ((tem (intern-soft buffer-string
+                                 minibuffer-completion-table)))
+           (if (or tem
+                   (and (string-equal buffer-string "nil")
+                        ;; intern-soft loses for 'nil
+                        (catch 'found
+                          (mapatoms #'(lambda (s)
+					(if (string-equal
+					     (symbol-name s)
+					     buffer-string)
+					    (throw 'found t)))
+				    minibuffer-completion-table)
+                          nil)))
+               (if minibuffer-completion-predicate
+                   (funcall minibuffer-completion-predicate
+                            tem)
+                   t)
+               nil)))
+        ((and (consp minibuffer-completion-table)
+              ;;#### Emacs-Lisp truly sucks!
+              ;; lambda, autoload, etc
+              (not (symbolp (car minibuffer-completion-table))))
+         (if (not completion-ignore-case)
+             (assoc buffer-string minibuffer-completion-table)
+             (let ((s (upcase buffer-string))
+                   (tail minibuffer-completion-table)
+                   tem)
+               (while tail
+                 (setq tem (car (car tail)))
+                 (if (or (equal tem buffer-string)
+                         (equal tem s)
+                         (equal (upcase tem) s))
+                     (setq s 'win
+                           tail nil)    ;exit
+                     (setq tail (cdr tail))))
+               (eq s 'win))))
+        (t
+         (funcall minibuffer-completion-table
+                  buffer-string
+                  minibuffer-completion-predicate
+                  'lambda)))
+  )
+
+;; 0 'none                 no possible completion
+;; 1 'unique               was already an exact and unique completion
+;; 3 'exact                was already an exact (but nonunique) completion
+;; NOT USED 'completed-exact-unique completed to an exact and completion 
+;; 4 'completed-exact      completed to an exact (but nonunique) completion
+;; 5 'completed            some completion happened
+;; 6 'uncompleted          no completion happened
+(defun minibuffer-do-completion-1 (buffer-string completion)
+  (cond ((not completion)
+         'none)
+        ((eq completion t)
+         ;; exact and unique match
+         'unique)
+        (t
+         ;; It did find a match.  Do we match some possibility exactly now?
+         (let ((completedp (not (string-equal completion buffer-string))))
+           (if completedp
+               (progn
+                 ;; Some completion happened
+                 (erase-buffer)
+                 (insert completion)
+                 (setq buffer-string completion)))
+           (if (exact-minibuffer-completion-p buffer-string)
+               ;; An exact completion was possible
+               (if completedp
+;; Since no callers need to know the difference, don't bother
+;;  with this (potentially expensive) discrimination.
+;;                 (if (eq (try-completion completion
+;;                                         minibuffer-completion-table
+;;                                         minibuffer-completion-predicate)
+;;                         't)
+;;                     'completed-exact-unique
+                       'completed-exact
+;;                     )
+                   'exact)
+               ;; Not an exact match
+               (if completedp
+                   'completed
+                   'uncompleted))))))
+
+
+(defun minibuffer-do-completion (buffer-string)
+  (let* ((completion (try-completion buffer-string
+                                     minibuffer-completion-table
+                                     minibuffer-completion-predicate))
+         (status (minibuffer-do-completion-1 buffer-string completion))
+         (last last-exact-completion))
+    (setq last-exact-completion nil)
+    (cond ((eq status 'none)
+           ;; No completions
+           (ding nil 'no-completion)
+           (temp-minibuffer-message " [No match]"))
+          ((eq status 'unique)
+           )
+          (t
+           ;; It did find a match.  Do we match some possibility exactly now?
+           (if (not (string-equal completion buffer-string))
+               (progn
+                 ;; Some completion happened
+                 (erase-buffer)
+                 (insert completion)
+                 (setq buffer-string completion)))
+           (cond ((eq status 'exact)
+                  ;; If the last exact completion and this one were
+                  ;;  the same, it means we've already given a
+                  ;;  "Complete but not unique" message and that the
+                  ;;  user's hit TAB again, so now we give help.
+                  (setq last-exact-completion completion)
+                  (if (equal buffer-string last)
+                      (minibuffer-completion-help)))
+                 ((eq status 'uncompleted)
+                  (if completion-auto-help
+                      (minibuffer-completion-help)
+                      (temp-minibuffer-message " [Next char not unique]")))
+                 (t
+                  nil))))
+    status))
+
+
+;;;; completing-read
+
+(defun completing-read (prompt table
+                        &optional predicate require-match
+                                  initial-contents history)
+  "Read a string in the minibuffer, with completion.
+Args: PROMPT, TABLE, PREDICATE, REQUIRE-MATCH, INITIAL-CONTENTS, HISTORY.
+PROMPT is a string to prompt with; normally it ends in a colon and a space.
+TABLE is an alist whose elements' cars are strings, or an obarray.
+PREDICATE limits completion to a subset of TABLE.
+See `try-completion' for more details on completion, TABLE, and PREDICATE.
+If REQUIRE-MATCH is non-nil, the user is not allowed to exit unless
+ the input is (or completes to) an element of TABLE or is null.
+ If it is also not t, Return does not exit if it does non-null completion.
+If INITIAL-CONTENTS is non-nil, insert it in the minibuffer initially.
+  If it is (STRING . POSITION), the initial input
+  is STRING, but point is placed POSITION characters into the string.
+HISTORY, if non-nil, specifies a history list
+  and optionally the initial position in the list.
+  It can be a symbol, which is the history list variable to use,
+  or it can be a cons cell (HISTVAR . HISTPOS).
+  In that case, HISTVAR is the history list variable to use,
+  and HISTPOS is the initial position (the position in the list
+  which INITIAL-CONTENTS corresponds to).
+  If HISTORY is `t', no history will be recorded.
+  Positions are counted starting from 1 at the beginning of the list.
+Completion ignores case if the ambient value of
+  `completion-ignore-case' is non-nil."
+  (let ((minibuffer-completion-table table)
+        (minibuffer-completion-predicate predicate)
+        (minibuffer-completion-confirm (if (eq require-match 't) nil t))
+        (last-exact-completion nil))
+    (read-from-minibuffer prompt
+                          initial-contents
+                          (if (not require-match)
+                              minibuffer-local-completion-map
+                              minibuffer-local-must-match-map)
+                          nil
+                          history)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                   Minibuffer completion commands                   ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+(defun minibuffer-complete ()
+  "Complete the minibuffer contents as far as possible.
+Return nil if there is no valid completion, else t.
+If no characters can be completed, display a list of possible completions.
+If you repeat this command after it displayed such a list,
+scroll the window of possible completions."
+  (interactive)
+  ;; If the previous command was not this, then mark the completion
+  ;;  buffer obsolete.
+  (or (eq last-command this-command)
+      (setq minibuffer-scroll-window nil))
+  (let ((window minibuffer-scroll-window))
+    (if (and window (windowp window) (window-buffer window)
+             (buffer-name (window-buffer window)))
+	;; If there's a fresh completion window with a live buffer
+	;;  and this command is repeated, scroll that window.
+	(let ((obuf (current-buffer)))
+          (unwind-protect
+	      (progn
+		(set-buffer (window-buffer window))
+		(if (pos-visible-in-window-p (point-max) window)
+		    ;; If end is in view, scroll up to the beginning.
+		    (set-window-start window (point-min))
+		  ;; Else scroll down one frame.
+		  (scroll-other-window)))
+	    (set-buffer obuf))
+          nil)
+      (let ((status (minibuffer-do-completion (buffer-string))))
+	(if (eq status 'none)
+	    nil
+	  (progn
+	    (cond ((eq status 'unique)
+		   (temp-minibuffer-message
+		    " [Sole completion]"))
+		  ((eq status 'exact)
+		   (temp-minibuffer-message
+		    " [Complete, but not unique]")))
+	    t))))))
+
+
+(defun minibuffer-complete-and-exit ()
+  "Complete the minibuffer contents, and maybe exit.
+Exit if the name is valid with no completion needed.
+If name was completed to a valid match,
+a repetition of this command will exit."
+  (interactive)
+  (if (= (point-min) (point-max))
+      ;; Crockishly allow user to specify null string
+      (throw 'exit nil))
+  (let ((buffer-string (buffer-string)))
+    ;; Short-cut -- don't call minibuffer-do-completion if we already
+    ;;  have an (possibly nonunique) exact completion.
+    (if (exact-minibuffer-completion-p buffer-string)
+        (throw 'exit nil))
+    (let ((status (minibuffer-do-completion buffer-string)))
+      (if (or (eq status 'unique)
+              (eq status 'exact)
+              (if (or (eq status 'completed-exact)
+                      (eq status 'completed-exact-unique))
+                  (if minibuffer-completion-confirm
+                      (progn (temp-minibuffer-message " [Confirm]")
+                             nil)
+                      t)))
+          (throw 'exit nil)))))
+
+
+(defun self-insert-and-exit ()
+  "Terminate minibuffer input."
+  (interactive)
+  (self-insert-command 1)
+  (throw 'exit nil))
+
+(defun exit-minibuffer ()
+  "Terminate this minibuffer argument.
+If minibuffer-confirm-incomplete is true, and we are in a completing-read
+of some kind, and the contents of the minibuffer is not an existing
+completion, requires an additional RET before the minibuffer will be exited
+\(assuming that RET was the character that invoked this command:
+the character in question must be typed again)."
+  (interactive)
+  (if (not minibuffer-confirm-incomplete)
+      (throw 'exit nil))
+  (let ((buffer-string (buffer-string)))
+    (if (exact-minibuffer-completion-p buffer-string)
+        (throw 'exit nil))
+    (let ((completion (if (not minibuffer-completion-table)
+                          t
+                          (try-completion buffer-string
+                                          minibuffer-completion-table
+                                          minibuffer-completion-predicate))))
+      (if (or (eq completion 't)
+              ;; Crockishly allow user to specify null string
+              (string-equal buffer-string ""))
+          (throw 'exit nil))
+      (if completion ;; rewritten for I18N3 snarfing
+	  (temp-minibuffer-message " [incomplete; confirm]")
+	(temp-minibuffer-message " [no completions; confirm]"))
+      (let ((event (let ((inhibit-quit t))
+		     (prog1
+			 (next-command-event)
+		       (setq quit-flag nil)))))
+        (cond ((equal event last-command-event)
+               (throw 'exit nil))
+              ((equal (quit-char) (event-to-character event))
+               ;; Minibuffer abort.
+               (throw 'exit t)))
+        (dispatch-event event)))))
+
+;;;; minibuffer-complete-word
+
+
+;;;#### I think I have done this correctly; it certainly is simpler
+;;;#### than what the C code seemed to be trying to do.
+(defun minibuffer-complete-word ()
+  "Complete the minibuffer contents at most a single word.
+After one word is completed as much as possible, a space or hyphen
+is added, provided that matches some possible completion.
+Return nil if there is no valid completion, else t."
+  (interactive)
+  (let* ((buffer-string (buffer-string))
+         (completion (try-completion buffer-string
+                                     minibuffer-completion-table
+                                     minibuffer-completion-predicate))
+         (status (minibuffer-do-completion-1 buffer-string completion)))
+    (cond ((eq status 'none)
+           (ding nil 'no-completion)
+           (temp-minibuffer-message " [No match]")
+           nil)
+          ((eq status 'unique)
+           ;; New message, only in this new Lisp code
+           (temp-minibuffer-message " [Sole completion]")
+           t)
+          (t
+           (cond ((or (eq status 'uncompleted)
+                      (eq status 'exact))
+                  (let ((foo #'(lambda (s)
+				 (condition-case nil
+				     (if (try-completion
+					  (concat buffer-string s)
+					  minibuffer-completion-table
+					  minibuffer-completion-predicate)
+					 (progn
+					   (goto-char (point-max))
+					   (insert s)
+					   t)
+                                       nil)
+                                   (error nil))))
+                        (char last-command-char))
+                    ;; Try to complete by adding a word-delimiter
+                    (or (and (characterp char) (> char 0)
+                             (funcall foo (char-to-string char)))
+                        (and (not (eq char ?\ ))
+                             (funcall foo " "))
+                        (and (not (eq char ?\-))
+                             (funcall foo "-"))
+                        (progn
+                          (if completion-auto-help 
+                              (minibuffer-completion-help)
+                              ;; New message, only in this new Lisp code
+			    ;; rewritten for I18N3 snarfing
+			    (if (eq status 'exact)
+				(temp-minibuffer-message
+				 " [Complete, but not unique]")
+			      (temp-minibuffer-message " [Ambiguous]")))
+                          nil))))
+                 (t
+                  (erase-buffer)
+                  (insert completion)
+                  ;; First word-break in stuff found by completion
+                  (goto-char (point-min))
+                  (let ((len (length buffer-string))
+                        n)
+                    (if (and (< len (length completion))
+                             (catch 'match
+                               (setq n 0)
+                               (while (< n len)
+                                 (if (char-equal
+                                       (upcase (aref buffer-string n))
+                                       (upcase (aref completion n)))
+                                     (setq n (1+ n))
+                                     (throw 'match nil)))
+                               t)
+                             (progn
+                               (goto-char (point-min))
+                               (forward-char len)
+                               (re-search-forward "\\W" nil t)))
+                        (delete-region (point) (point-max))
+                        (goto-char (point-max))))
+                  t))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                      "Smart minibuffer" hackery                    ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; ("Kludgy minibuffer hackery" is perhaps a better name)
+
+;; This works by setting `mouse-grabbed-buffer' to the minibuffer,
+;; defining button2 in the minibuffer keymap to
+;; `minibuffer-smart-select-highlighted-completion', and setting the
+;; mode-motion-hook of the minibuffer to `minibuffer-mouse-tracker'.
+;; By setting `mouse-grabbed-buffer', the minibuffer's keymap and
+;; mode-motion-hook apply (for mouse motion and presses) no matter
+;; what buffer the mouse is over.  Then, `minibuffer-mouse-tracker'
+;; examines the text under the mouse looking for something that looks
+;; like a completion, and causes it to be highlighted, and
+;; `minibuffer-smart-select-highlighted-completion' looks for a
+;; flagged completion under the mouse and inserts it.  This has the
+;; following advantages:
+;;
+;; -- filenames and such in any buffer can be inserted by clicking,
+;;    not just completions
+;;
+;; but the following disadvantages:
+;;
+;; -- unless you're aware of the "filename in any buffer" feature,
+;;    the fact that strings in arbitrary buffers get highlighted appears
+;;    as a bug
+;; -- mouse motion can cause ange-ftp actions -- bad bad bad.
+;;
+;; There's some hackery in minibuffer-mouse-tracker to try to avoid the
+;; ange-ftp stuff, but it doesn't work.
+;;
+
+(defcustom minibuffer-smart-completion-tracking-behavior nil
+  "*If non-nil, look for completions under mouse in all buffers.
+This allows you to click on something that looks like a completion
+and have it selected, regardless of what buffer it is in.
+
+This is not enabled by default because
+
+-- The \"mysterious\" highlighting in normal buffers is confusing to
+   people not expecting it, and looks like a bug
+-- If ange-ftp is enabled, this tracking sometimes causes ange-ftp
+   action as a result of mouse motion, which is *bad bad bad*.
+   Hopefully this bug will be fixed at some point."
+  :type 'boolean
+  :group 'minibuffer)
+
+(defun minibuffer-smart-mouse-tracker (event)
+  ;; Used as the mode-motion-hook of the minibuffer window, which is the
+  ;; value of `mouse-grabbed-buffer' while the minibuffer is active.  If
+  ;; the word under the mouse is a valid minibuffer completion, then it
+  ;; is highlighted.
+  ;;
+  ;; We do some special voodoo when we're reading a pathname, because
+  ;; the way filename completion works is funny.  Possibly there's some
+  ;; more general way this could be dealt with...
+  ;;
+  ;; We do some further voodoo when reading a pathname that is an
+  ;; ange-ftp or efs path, because causing FTP activity as a result of
+  ;; mouse motion is a really bad time.
+  ;;
+  (and minibuffer-smart-completion-tracking-behavior
+       (event-point event)
+       ;; avoid conflict with display-completion-list extents
+       (not (extent-at (event-point event)
+		       (event-buffer event)
+		       'list-mode-item))
+       (let ((filename-kludge-p (eq minibuffer-completion-table
+				    'read-file-name-internal)))
+	 (mode-motion-highlight-internal
+	  event
+	  #'(lambda () (default-mouse-track-beginning-of-word
+			 (if filename-kludge-p 'nonwhite t)))
+	  #'(lambda ()
+	      (let ((p (point))
+		    (string ""))
+		(default-mouse-track-end-of-word
+		  (if filename-kludge-p 'nonwhite t))
+		(if (and (/= p (point)) minibuffer-completion-table)
+		    (setq string (buffer-substring p (point))))
+		(if (string-match "\\`[ \t\n]*\\'" string)
+		    (goto-char p)
+		  (if filename-kludge-p
+		      (setq string (minibuffer-smart-select-kludge-filename
+				    string)))
+		  ;; try-completion bogusly returns a string even when
+		  ;; that string is complete if that string is also a
+		  ;; prefix for other completions.  This means that we
+		  ;; can't just do the obvious thing, (eq t
+		  ;; (try-completion ...)).
+		  (let (comp)
+		    (if (and filename-kludge-p
+			     ;; #### evil evil evil evil
+			     (or (and (fboundp 'ange-ftp-ftp-path)
+				      (ange-ftp-ftp-path string))
+				 (and (fboundp 'efs-ftp-path)
+				      (efs-ftp-path string))))
+			(setq comp t)
+		      (setq comp
+			    (try-completion string
+					    minibuffer-completion-table
+					    minibuffer-completion-predicate)))
+		    (or (eq comp t)
+			(and (equal comp string)
+			     (or (null minibuffer-completion-predicate)
+				 (stringp
+				  minibuffer-completion-predicate) ; ???
+				 (funcall minibuffer-completion-predicate
+					  (if (vectorp
+					       minibuffer-completion-table)
+					      (intern-soft
+					       string
+					       minibuffer-completion-table)
+					    string))))
+			(goto-char p))))))))))
+
+(defun minibuffer-smart-select-kludge-filename (string)
+  (save-excursion
+    (set-buffer mouse-grabbed-buffer) ; the minibuf
+    (let ((kludge-string (concat (buffer-string) string)))
+      (if (or (and (fboundp 'ange-ftp-ftp-path)
+		   (ange-ftp-ftp-path kludge-string))
+	       (and (fboundp 'efs-ftp-path) (efs-ftp-path kludge-string)))
+	   ;; #### evil evil evil, but more so.
+	   string
+	 (append-expand-filename (buffer-string) string)))))
+
+(defun minibuffer-smart-select-highlighted-completion (event)
+  "Select the highlighted text under the mouse as a minibuffer response.
+When the minibuffer is being used to prompt the user for a completion,
+any valid completions which are visible on the frame will highlight
+when the mouse moves over them.  Clicking \\<minibuffer-local-map>\
+\\[minibuffer-smart-select-highlighted-completion] will select the
+highlighted completion under the mouse.
+
+If the mouse is clicked while not over a highlighted completion,
+then the global binding of \\[minibuffer-smart-select-highlighted-completion] \
+will be executed instead.  In this\nway you can get at the normal global \
+behavior of \\[minibuffer-smart-select-highlighted-completion] as well as
+the special minibuffer behavior."
+  (interactive "e")
+  (if minibuffer-smart-completion-tracking-behavior
+      (minibuffer-smart-select-highlighted-completion-1 event t)
+    (let ((command (lookup-key global-map
+			       (vector current-mouse-event))))
+      (if command (call-interactively command)))))
+
+(defun minibuffer-smart-select-highlighted-completion-1 (event global-p)
+  (let* ((filename-kludge-p (eq minibuffer-completion-table
+				'read-file-name-internal))
+	 completion
+	 command-p
+	 (evpoint (event-point event))
+	 (evextent (and evpoint (extent-at evpoint (event-buffer event)
+					   'list-mode-item))))
+    (if evextent
+	;; avoid conflict with display-completion-list extents.
+	;; if we find one, do that behavior instead.
+	(list-mode-item-selected-1 evextent event)
+      (save-excursion
+	(let* ((buffer (window-buffer (event-window event)))
+	       (p (event-point event))
+	       (extent (and p (extent-at p buffer 'mouse-face))))
+	  (set-buffer buffer)
+	  (if (not (and (extent-live-p extent)
+			(eq (extent-object extent) (current-buffer))
+			(not (extent-detached-p extent))))
+	      (setq command-p t)
+	    ;; ...else user has selected a highlighted completion.
+	    (setq completion
+		  (buffer-substring (extent-start-position extent)
+				    (extent-end-position extent)))
+	    (if filename-kludge-p
+		(setq completion (minibuffer-smart-select-kludge-filename
+				  completion)))
+	    ;; remove the extent so that it's not hanging around in
+	    ;; *Completions*
+	    (detach-extent extent)
+	    (set-buffer mouse-grabbed-buffer)
+	    (erase-buffer)
+	    (insert completion))))
+      ;; we need to execute the command or do the throw outside of the
+      ;; save-excursion.
+      (cond ((and command-p global-p)
+	     (let ((command (lookup-key global-map
+					(vector current-mouse-event))))
+	       (if command
+		   (call-interactively command)
+		 (if minibuffer-completion-table
+		     (error
+		      "Highlighted words are valid completions.  You may select one.")
+		   (error "no completions")))))
+	    ((not command-p)
+	     ;; things get confused if the minibuffer is terminated while
+	     ;; not selected.
+	     (select-window (minibuffer-window))
+	     (if (and filename-kludge-p (file-directory-p completion))
+		 ;; if the user clicked middle on a directory name, display the
+		 ;; files in that directory.
+		 (progn
+		   (goto-char (point-max))
+		   (minibuffer-completion-help))
+	       ;; otherwise, terminate input
+	       (throw 'exit nil)))))))
+
+(defun minibuffer-smart-maybe-select-highlighted-completion
+  (event &optional click-count)
+  "Like minibuffer-smart-select-highlighted-completion but does nothing if
+there is no completion (as opposed to executing the global binding).  Useful
+as the value of `mouse-track-click-hook'."
+  (interactive "e")
+  (minibuffer-smart-select-highlighted-completion-1 event nil))
+
+(define-key minibuffer-local-map 'button2
+  'minibuffer-smart-select-highlighted-completion)
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                         Minibuffer History                         ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar minibuffer-history '()
+  "Default minibuffer history list.
+This is used for all minibuffer input except when an alternate history
+list is specified.")
+
+;; Some other history lists:
+;;
+(defvar minibuffer-history-search-history '())
+(defvar function-history '())
+(defvar variable-history '())
+(defvar buffer-history '())
+(defvar shell-command-history '())
+(defvar file-name-history '())
+
+(defvar read-expression-history nil)
+
+(defvar minibuffer-history-sexp-flag nil ;weird FSF Emacs kludge
+  "Non-nil when doing history operations on `command-history'.
+More generally, indicates that the history list being acted on
+contains expressions rather than strings.")
+
+(defun previous-matching-history-element (regexp n)
+  "Find the previous history element that matches REGEXP.
+\(Previous history elements refer to earlier actions.)
+With prefix argument N, search for Nth previous match.
+If N is negative, find the next or Nth next match."
+  (interactive
+   (let ((enable-recursive-minibuffers t)
+	 (minibuffer-history-sexp-flag nil))
+     (if (eq 't (symbol-value minibuffer-history-variable))
+	 (error "History is not being recorded in this context"))
+     (list (read-from-minibuffer "Previous element matching (regexp): "
+				 (car minibuffer-history-search-history)
+				 minibuffer-local-map
+				 nil
+				 'minibuffer-history-search-history)
+	   (prefix-numeric-value current-prefix-arg))))
+  (let ((history (symbol-value minibuffer-history-variable))
+	prevpos
+	(pos minibuffer-history-position))
+    (if (eq history t)
+	(error "History is not being recorded in this context"))
+    (while (/= n 0)
+      (setq prevpos pos)
+      (setq pos (min (max 1 (+ pos (if (< n 0) -1 1))) (length history)))
+      (if (= pos prevpos)
+	  (if (= pos 1) ;; rewritten for I18N3 snarfing
+	      (error "No later matching history item")
+	    (error "No earlier matching history item")))
+      (if (string-match regexp
+			(if minibuffer-history-sexp-flag
+			    (let ((print-level nil))
+			      (prin1-to-string (nth (1- pos) history)))
+                            (nth (1- pos) history)))
+	  (setq n (+ n (if (< n 0) 1 -1)))))
+    (setq minibuffer-history-position pos)
+    (setq current-minibuffer-contents (buffer-string)
+	  current-minibuffer-point (point))
+    (erase-buffer)
+    (let ((elt (nth (1- pos) history)))
+      (insert (if minibuffer-history-sexp-flag
+		  (let ((print-level nil))
+		    (prin1-to-string elt))
+                  elt)))
+      (goto-char (point-min)))
+  (if (or (eq (car (car command-history)) 'previous-matching-history-element)
+	  (eq (car (car command-history)) 'next-matching-history-element))
+      (setq command-history (cdr command-history))))
+
+(defun next-matching-history-element (regexp n)
+  "Find the next history element that matches REGEXP.
+\(The next history element refers to a more recent action.)
+With prefix argument N, search for Nth next match.
+If N is negative, find the previous or Nth previous match."
+  (interactive
+   (let ((enable-recursive-minibuffers t)
+	 (minibuffer-history-sexp-flag nil))
+     (if (eq t (symbol-value minibuffer-history-variable))
+	 (error "History is not being recorded in this context"))
+     (list (read-from-minibuffer "Next element matching (regexp): "
+				 (car minibuffer-history-search-history)
+				 minibuffer-local-map
+				 nil
+				 'minibuffer-history-search-history)
+	   (prefix-numeric-value current-prefix-arg))))
+  (previous-matching-history-element regexp (- n)))
+
+(defun next-history-element (n)
+  "Insert the next element of the minibuffer history into the minibuffer."
+  (interactive "p")
+  (if (eq 't (symbol-value minibuffer-history-variable))
+      (error "History is not being recorded in this context"))
+  (unless (zerop n)
+    (when (eq minibuffer-history-position
+	      initial-minibuffer-history-position)
+      (setq current-minibuffer-contents (buffer-string)
+	    current-minibuffer-point (point)))
+    (let ((narg (- minibuffer-history-position n)))
+      (cond ((< narg 0)
+	     (error "No following item in %s" minibuffer-history-variable))
+	    ((> narg (length (symbol-value minibuffer-history-variable)))
+	     (error "No preceding item in %s" minibuffer-history-variable)))
+      (erase-buffer)
+      (setq minibuffer-history-position narg)
+      (if (eq narg initial-minibuffer-history-position)
+	  (progn
+	    (insert current-minibuffer-contents)
+	    (goto-char current-minibuffer-point))
+	(let ((elt (nth (1- minibuffer-history-position)
+			(symbol-value minibuffer-history-variable))))
+	  (insert
+	   (if (not (stringp elt))
+	       (let ((print-level nil))
+		 (condition-case nil
+		     (let ((print-readably t)
+			   (print-escape-newlines t))
+		       (prin1-to-string elt))
+		   (error (prin1-to-string elt))))
+	     elt)))
+	;; FSF has point-min here.
+	(goto-char (point-max))))))
+
+(defun previous-history-element (n)
+  "Inserts the previous element of the minibuffer history into the minibuffer."
+  (interactive "p")
+  (next-history-element (- n)))
+
+(defun next-complete-history-element (n)
+  "Get next element of history which is a completion of minibuffer contents."
+  (interactive "p")
+  (let ((point-at-start (point)))
+    (next-matching-history-element
+     (concat "^" (regexp-quote (buffer-substring (point-min) (point)))) n)
+    ;; next-matching-history-element always puts us at (point-min).
+    ;; Move to the position we were at before changing the buffer contents.
+    ;; This is still sensical, because the text before point has not changed.
+    (goto-char point-at-start)))
+
+(defun previous-complete-history-element (n)
+  "Get previous element of history which is a completion of minibuffer contents."
+  (interactive "p")
+  (next-complete-history-element (- n)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                reading various things from a minibuffer            ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun read-expression (prompt &optional initial-contents history)
+  "Return a Lisp object read using the minibuffer.
+Prompt with PROMPT.  If non-nil, optional second arg INITIAL-CONTENTS
+is a string to insert in the minibuffer before reading.
+Third arg HISTORY, if non-nil, specifies a history list."
+  (let ((minibuffer-history-sexp-flag t)
+	;; Semi-kludge to get around M-x C-x o M-ESC trying to do completion.
+	(minibuffer-completion-table nil))
+    (read-from-minibuffer prompt
+			  initial-contents
+			  read-expression-map
+			  t
+			  (or history 'read-expression-history)
+			  lisp-mode-abbrev-table)))
+
+(defun read-string (prompt &optional initial-contents history)
+  "Return a string from the minibuffer, prompting with string PROMPT.
+If non-nil, optional second arg INITIAL-CONTENTS is a string to insert
+in the minibuffer before reading.
+Third arg HISTORY, if non-nil, specifies a history list."
+  (let ((minibuffer-completion-table nil))
+    (read-from-minibuffer prompt
+			  initial-contents
+			  minibuffer-local-map
+			  nil history)))
+
+(defun eval-minibuffer (prompt &optional initial-contents history)
+  "Return value of Lisp expression read using the minibuffer.
+Prompt with PROMPT.  If non-nil, optional second arg INITIAL-CONTENTS
+is a string to insert in the minibuffer before reading.
+Third arg HISTORY, if non-nil, specifies a history list."
+  (eval (read-expression prompt initial-contents history)))
+
+;;;#### Screw this crock!!
+;(defun read-no-blanks-input (prompt &optional initial-contents)
+; "Read a string from the terminal, not allowing blanks.
+;Prompt with PROMPT.  If non-nil, optional second arg INITIAL-CONTENTS
+;is a string to insert in the minibuffer before reading."
+;  (let ((minibuffer-completion-table nil))
+; (read-from-minibuffer prompt
+;                       initial-contents
+;                       minibuffer-local-ns-map
+;                       nil)))
+
+;; The name `command-history' is already taken
+(defvar read-command-history '())
+
+(defun read-command (prompt)
+  "Read the name of a command and return as a symbol.
+Prompts with PROMPT."
+  (intern (completing-read prompt obarray 'commandp t nil
+			   ;; 'command-history is not right here: that's a
+			   ;; list of evalable forms, not a history list.
+			   'read-command-history
+			   )))
+
+(defun read-function (prompt)
+  "Read the name of a function and return as a symbol.
+Prompts with PROMPT."
+  (intern (completing-read prompt obarray 'fboundp t nil
+			   'function-history)))
+
+(defun read-variable (prompt)
+  "Read the name of a user variable and return it as a symbol.
+Prompts with PROMPT.
+A user variable is one whose documentation starts with a `*' character."
+  (intern (completing-read prompt obarray 'user-variable-p t nil
+			   'variable-history)))
+
+(defun read-buffer (prompt &optional default require-match)
+  "Read the name of a buffer and return as a string.
+Prompts with PROMPT.  Optional second arg DEFAULT is value to return if user
+enters an empty line.  If optional third arg REQUIRE-MATCH is non-nil,
+only existing buffer names are allowed."
+  (let ((prompt (if default 
+                    (format "%s(default %s) "
+                            (gettext prompt) (if (bufferp default)
+						 (buffer-name default)
+					       default))
+                    prompt))
+        (alist (mapcar #'(lambda (b) (cons (buffer-name b) b))
+                       (buffer-list)))
+        result)
+    (while (progn
+             (setq result (completing-read prompt alist nil require-match
+					   nil 'buffer-history))
+             (cond ((not (equal result ""))
+                    nil)
+                   ((not require-match)
+                    (setq result default)
+                    nil)
+                   ((not default)
+                    t)
+                   ((not (get-buffer default))
+                    t)
+                   (t
+                    (setq result default)
+                    nil))))
+    (if (bufferp result)
+        (buffer-name result)
+      result)))
+
+(defun read-number (prompt &optional integers-only)
+  "Reads a number from the minibuffer."
+  (let ((pred (if integers-only 'integerp 'numberp))
+	num)
+    (while (not (funcall pred num))
+      (setq num (condition-case ()
+		    (let ((minibuffer-completion-table nil))
+		      (read-from-minibuffer
+		       prompt (if num (prin1-to-string num)) nil t
+		       t)) ;no history
+		  (invalid-read-syntax nil)
+		  (end-of-file nil)))
+      (or (funcall pred num) (beep)))
+    num))
+
+(defun read-shell-command (prompt &optional initial-input history)
+  "Just like read-string, but uses read-shell-command-map:
+\\{read-shell-command-map}"
+  (let ((minibuffer-completion-table nil))
+    (read-from-minibuffer prompt initial-input read-shell-command-map
+			  nil (or history 'shell-command-history))))
+
+
+;;; This read-file-name stuff probably belongs in files.el
+
+;; Quote "$" as "$$" to get it past substitute-in-file-name
+(defun un-substitute-in-file-name (string)
+  (let ((regexp "\\$")
+        (olen (length string))
+        new
+        n o ch)
+    (cond ((eq system-type 'vax-vms)
+           string)
+          ((not (string-match regexp string))
+           string)
+          (t
+           (setq n 1)
+           (while (string-match regexp string (match-end 0))
+             (setq n (1+ n)))
+           (setq new (make-string (+ olen n) ?$))
+           (setq n 0 o 0)
+           (while (< o olen)
+             (setq ch (aref string o))
+             (aset new n ch)
+             (setq o (1+ o) n (1+ n))
+             (if (eq ch ?$)
+                 ;; already aset by make-string initial-value
+                 (setq n (1+ n))))
+           new))))
+  
+(defun read-file-name-2 (history prompt dir default 
+				 must-match initial-contents
+				 completer)
+  (if (not dir)
+      (setq dir default-directory))
+  (setq dir (abbreviate-file-name dir t))
+  (let* ((insert (cond ((and (not insert-default-directory)
+			     (not initial-contents))
+                        "")
+                       (initial-contents
+                        (cons (un-substitute-in-file-name
+			       (concat dir initial-contents))
+                              (length dir)))
+                       (t
+                        (un-substitute-in-file-name dir))))
+         (val (let ((completion-ignore-case (or completion-ignore-case
+						(eq system-type 'vax-vms))))
+                ;;  Hateful, broken, case-sensitive un*x
+;;;                 (completing-read prompt
+;;;                                  completer
+;;;                                  dir
+;;;                                  must-match
+;;;                                  insert
+;;;                                  history)
+		;; #### - this is essentially the guts of completing read.
+		;; There should be an elegant way to pass a pair of keymaps to
+		;; completing read, but this will do for now.  All sins are
+		;; relative.  --Stig
+		(let ((minibuffer-completion-table completer)
+		      (minibuffer-completion-predicate dir)
+		      (minibuffer-completion-confirm (if (eq must-match 't)
+							 nil t))
+		      (last-exact-completion nil))
+		  (read-from-minibuffer prompt
+					insert
+					(if (not must-match)
+					    read-file-name-map
+					  read-file-name-must-match-map)
+					nil
+					history)))
+	      ))
+;;;     ;; Kludge!  Put "/foo/bar" on history rather than "/default//foo/bar"
+;;;     (let ((hist (cond ((not history) 'minibuffer-history)
+;;;                       ((consp history) (car history))
+;;;                       (t history))))
+;;;       (if (and val
+;;;                hist
+;;;                (not (eq hist 't))
+;;;                (boundp hist)
+;;;                (equal (car-safe (symbol-value hist)) val))
+;;;           (let ((e (condition-case nil
+;;;                        (expand-file-name val)
+;;;                      (error nil))))
+;;;             (if (and e (not (equal e val)))
+;;;                 (set hist (cons e (cdr (symbol-value hist))))))))
+
+    (cond ((not val)
+           (error "No file name specified"))
+          ((and default
+                (equal val (if (consp insert) (car insert) insert)))
+           default)
+          (t
+           (substitute-in-file-name val)))))
+
+;; #### this function should use minibuffer-completion-table
+;; or something.  But that is sloooooow.
+;; #### all this shit needs better documentation!!!!!!!!
+(defun read-file-name-activate-callback (event extent dir-p)
+  ;; used as the activate-callback of the filename list items
+  ;; in the completion buffer, in place of default-choose-completion.
+  ;; if a regular file was selected, we call default-choose-completion
+  ;; (which just inserts the string in the minibuffer and calls
+  ;; exit-minibuffer).  If a directory was selected, we display
+  ;; the contents of the directory.
+  (let* ((file (extent-string extent))
+	 (completion-buf (extent-object extent))
+	 (minibuf (symbol-value-in-buffer 'completion-reference-buffer
+					  completion-buf))
+	 (in-dir (file-name-directory (buffer-substring nil nil minibuf)))
+	 (full (expand-file-name file in-dir)))
+    (if (not (file-directory-p full))
+	(default-choose-completion event extent minibuf)
+      (erase-buffer minibuf)
+      (insert-string (file-name-as-directory
+		      (abbreviate-file-name full t)) minibuf)
+      (reset-buffer completion-buf)
+      (let ((standard-output completion-buf))
+	(display-completion-list
+	 (delete "." (directory-files full nil nil nil (if dir-p 'directory)))
+	 :user-data dir-p
+	 :reference-buffer minibuf
+	 :activate-callback 'read-file-name-activate-callback)
+	(goto-char (point-min) completion-buf)))))
+
+(defun read-file-name-1 (history prompt dir default 
+				 must-match initial-contents
+				 completer)
+  (if (should-use-dialog-box-p)
+      ;; this calls read-file-name-2
+      (mouse-read-file-name-1 history prompt dir default must-match
+			      initial-contents completer)
+    (let ((rfhookfun
+	   (lambda ()
+	     (set
+	      (make-local-variable
+	       'completion-display-completion-list-function)
+	      #'(lambda (completions)
+		  (display-completion-list
+		   completions
+		   :user-data (not (eq completer 'read-file-name-internal))
+		   :activate-callback
+		   'read-file-name-activate-callback)))
+	     ;; kludge!
+	     (remove-hook 'minibuffer-setup-hook rfhookfun)
+	     )))
+      (unwind-protect
+	  (progn
+	    (add-hook 'minibuffer-setup-hook rfhookfun)
+	    (read-file-name-2 history prompt dir default must-match
+			      initial-contents completer))
+	(remove-hook 'minibuffer-setup-hook rfhookfun)))))
+
+(defun read-file-name (prompt
+                       &optional dir default must-match initial-contents
+		       history)
+  "Read file name, prompting with PROMPT and completing in directory DIR.
+This will prompt with a dialog box if appropriate, according to
+ `should-use-dialog-box-p'.
+Value is not expanded---you must call `expand-file-name' yourself.
+Value is subject to interpreted by substitute-in-file-name however.
+Default name to DEFAULT if user enters a null string.
+ (If DEFAULT is omitted, the visited file name is used,
+  except that if INITIAL-CONTENTS is specified, that combined with DIR is
+  used.)
+Fourth arg MUST-MATCH non-nil means require existing file's name.
+ Non-nil and non-t means also require confirmation after completion.
+Fifth arg INITIAL-CONTENTS specifies text to start with.
+Sixth arg HISTORY specifies the history list to use.  Default is
+ `file-name-history'.
+DIR defaults to current buffer's directory default."
+  (read-file-name-1
+   (or history 'file-name-history)
+   prompt dir (or default
+		  (if initial-contents (expand-file-name initial-contents dir)
+		    buffer-file-name))
+   must-match initial-contents
+   ;; A separate function (not an anonymous lambda-expression)
+   ;; and passed as a symbol because of disgusting kludges in various
+   ;; places which do stuff like (let ((filename-kludge-p (eq minibuffer-completion-table 'read-file-name-internal))) ...)
+   'read-file-name-internal))
+
+(defun read-directory-name (prompt
+                            &optional dir default must-match initial-contents)
+  "Read directory name, prompting with PROMPT and completing in directory DIR.
+This will prompt with a dialog box if appropriate, according to
+ `should-use-dialog-box-p'.
+Value is not expanded---you must call `expand-file-name' yourself.
+Value is subject to interpreted by substitute-in-file-name however.
+Default name to DEFAULT if user enters a null string.
+ (If DEFAULT is omitted, the current buffer's default directory is used.)
+Fourth arg MUST-MATCH non-nil means require existing directory's name.
+ Non-nil and non-t means also require confirmation after completion.
+Fifth arg INITIAL-CONTENTS specifies text to start with.
+Sixth arg HISTORY specifies the history list to use.  Default is
+ `file-name-history'.
+DIR defaults to current buffer's directory default."
+  (read-file-name-1 
+    'file-name-history
+    prompt dir (or default default-directory) must-match initial-contents
+    'read-directory-name-internal))
+
+
+;; Environment-variable completion hack
+(defun read-file-name-internal-1 (string dir action completer)
+  (if (not (string-match
+	    "\\([^$]\\|\\`\\)\\(\\$\\$\\)*\\$\\([A-Za-z0-9_]*\\|{[^}]*\\)\\'"
+	    string))
+      ;; Not doing environment-variable completion hack
+      (let* ((orig (if (equal string "") nil string))
+             (sstring (if orig (substitute-in-file-name string) string))
+             (specdir (if orig (file-name-directory sstring) nil)))
+        (funcall completer 
+                 action 
+                 orig 
+                 sstring 
+                 specdir
+                 (if specdir (expand-file-name specdir dir) dir)
+                 (if orig (file-name-nondirectory sstring) string)))
+      ;; An odd number of trailing $'s
+      (let* ((start (match-beginning 3))
+             (env (substring string 
+                             (cond ((= start (length string))
+                                    ;; "...$"
+                                    start)
+                                   ((= (aref string start) ?{)
+                                    ;; "...${..."
+                                    (1+ start))
+                                   (t
+                                    start))))
+             (head (substring string 0 (1- start)))
+             (alist #'(lambda ()
+                        (mapcar #'(lambda (x)
+                                    (cons (substring x 0 (string-match "=" x))
+                                          'nil))
+                                process-environment))))
+        
+	(cond ((eq action 'lambda)
+               nil)
+              ((eq action 't)
+               ;; all completions
+               (mapcar #'(lambda (p)
+			   (if (and (> (length p) 0)
+				    ;;#### Unix-specific
+				    ;;####  -- need absolute-pathname-p
+				    (/= (aref p 0) ?/))
+			       (concat "$" p)
+                             (concat head "$" p)))
+                       (all-completions env (funcall alist))))
+              (t ;; 'nil
+               ;; complete
+               (let* ((e (funcall alist))
+                      (val (try-completion env e)))
+                 (cond ((stringp val)
+                        (if (string-match "[^A-Za-z0-9_]" val)
+                            (concat head
+                                    "${" val
+                                    ;; completed uniquely?
+                                    (if (eq (try-completion val e) 't)
+                                        "}" ""))
+                            (concat head "$" val)))
+                       ((eql val 't)
+                        (concat head
+                                (un-substitute-in-file-name (getenv env))))
+                       (t nil))))))))
+
+
+(defun read-file-name-internal (string dir action)
+  (read-file-name-internal-1 
+   string dir action
+   #'(lambda (action orig string specdir dir name)
+      (cond ((eq action 'lambda)
+             (if (not orig)
+                 nil
+               (let ((sstring (condition-case nil 
+                                  (expand-file-name string)
+                                (error nil))))
+                 (if (not sstring)
+                     ;; Some pathname syntax error in string
+                     nil
+                     (file-exists-p sstring)))))
+            ((eq action 't)
+             ;; all completions
+             (mapcar #'un-substitute-in-file-name
+                     (file-name-all-completions name dir)))
+            (t;; 'nil
+             ;; complete
+             (let* ((d (or dir default-directory))
+		    (val (file-name-completion name d)))
+               (if (and (eq val 't)
+                        (not (null completion-ignored-extensions)))
+                   ;;#### (file-name-completion "foo") returns 't
+                   ;;   when both "foo" and "foo~" exist and the latter
+                   ;;   is "pruned" by completion-ignored-extensions.
+                   ;; I think this is a bug in file-name-completion.
+                   (setq val (let ((completion-ignored-extensions '()))
+                               (file-name-completion name d))))
+               (if (stringp val)
+                   (un-substitute-in-file-name (if specdir
+                                                   (concat specdir val)
+                                                   val))
+                   (let ((tem (un-substitute-in-file-name string)))
+                     (if (not (equal tem orig))
+                         ;; substitute-in-file-name did something
+                         tem
+                         val)))))))))
+
+(defun read-directory-name-internal (string dir action)
+  (read-file-name-internal-1 
+   string dir action
+   #'(lambda (action orig string specdir dir name)
+      (let* ((dirs #'(lambda (fn)
+		       (let ((l (if (equal name "")
+				    (directory-files
+				     dir
+				     nil
+				     ""
+				     nil
+				     'directories)
+				  (directory-files
+				   dir
+				   nil 
+				   (concat "\\`" (regexp-quote name))
+				   nil
+				   'directories))))
+			 (mapcar fn
+				 (cond ((eq system-type 'vax-vms)
+					l)
+				       (t
+					;; Wretched unix
+					(delete "." l))))))))
+        (cond ((eq action 'lambda)
+               ;; complete?
+               (if (not orig)
+                   nil
+		 (file-directory-p string)))
+              ((eq action 't)
+               ;; all completions
+               (funcall dirs #'(lambda (n)
+				 (un-substitute-in-file-name 
+				  (file-name-as-directory n)))))
+              (t
+               ;; complete
+               (let ((val (try-completion
+                           name
+                           (funcall dirs
+                                    #'(lambda (n)
+					(list (file-name-as-directory
+					       n)))))))
+                 (if (stringp val)
+                     (un-substitute-in-file-name (if specdir
+                                                     (concat specdir val)
+						   val))
+		   (let ((tem (un-substitute-in-file-name string)))
+		     (if (not (equal tem orig))
+			 ;; substitute-in-file-name did something
+			 tem
+		       val))))))))))
+
+(defun append-expand-filename (file-string string)
+  "Append STRING to FILE-STRING differently depending on whether STRING
+is a username (~string), an environment variable ($string), 
+or a filename (/string).  The resultant string is returned with the 
+environment variable or username expanded and resolved to indicate 
+whether it is a file(/result) or a directory (/result/)."
+  (let ((file 
+	 (cond ((string-match "\\([~$]\\)\\([^~$/]*\\)$" file-string)
+		(cond ((string= (substring file-string 
+					   (match-beginning 1)
+					   (match-end 1)) "~")
+		       (concat (substring file-string 0 (match-end 1))
+			       string))
+		      (t (substitute-in-file-name
+			  (concat (substring file-string 0 (match-end 1))
+				  string)))))
+	       (t (concat (file-name-directory 
+			   (substitute-in-file-name file-string)) string))))
+	result)
+    
+    (cond ((stringp (setq result (and (file-exists-p (expand-file-name file))
+				      (read-file-name-internal 
+				       (condition-case nil
+					   (expand-file-name file)
+					 (error file))
+				       "" nil))))
+	   result)
+	  (t file))))
+
+(defun mouse-file-display-completion-list (window dir minibuf user-data)
+  (let ((standard-output (window-buffer window)))
+    (condition-case nil
+	(display-completion-list 
+	 (directory-files dir nil nil nil t)
+	 :window-width (* 2 (window-width window))
+	 :activate-callback
+	 'mouse-read-file-name-activate-callback
+	 :user-data user-data
+	 :reference-buffer minibuf
+	 :help-string "")
+      (t nil))))
+
+(defun mouse-directory-display-completion-list (window dir minibuf user-data)
+  (let ((standard-output (window-buffer window)))
+    (condition-case nil
+	(display-completion-list
+	 (delete "." (directory-files dir nil nil nil 1))
+	 :window-width (window-width window)
+	 :activate-callback
+	 'mouse-read-file-name-activate-callback
+	 :user-data user-data
+	 :reference-buffer minibuf
+	 :help-string "")
+      (t nil))))
+
+(defun mouse-read-file-name-activate-callback (event extent user-data)
+  (let* ((file (extent-string extent))
+	 (minibuf (symbol-value-in-buffer 'completion-reference-buffer
+					  (extent-object extent)))
+	 (in-dir (buffer-substring nil nil minibuf))
+	 (full (expand-file-name file in-dir))
+	 (filebuf (nth 0 user-data))
+	 (dirbuff (nth 1 user-data))
+	 (filewin (nth 2 user-data))
+	 (dirwin (nth 3 user-data)))
+    (if (file-regular-p full)
+	(default-choose-completion event extent minibuf)
+      (erase-buffer minibuf)
+      (insert-string (file-name-as-directory
+		      (abbreviate-file-name full t)) minibuf)
+      (reset-buffer filebuf)
+      (if (not dirbuff)
+	  (mouse-directory-display-completion-list filewin full minibuf
+						   user-data)
+	(mouse-file-display-completion-list filewin full minibuf user-data)
+	(reset-buffer dirbuff)
+	(mouse-directory-display-completion-list dirwin full minibuf
+						 user-data)))))
+
+;; this is rather cheesified but gets the job done.
+(defun mouse-read-file-name-1 (history prompt dir default 
+				 must-match initial-contents
+				 completer)
+  (let* ((file-p (eq 'read-file-name-internal completer))
+	 (filebuf (get-buffer-create "*Completions*"))
+	 (dirbuff (and file-p (generate-new-buffer " *mouse-read-file*")))
+	 (butbuff (generate-new-buffer " *mouse-read-file*"))
+	 (frame (make-dialog-frame))
+	 filewin dirwin
+	 user-data)
+    (unwind-protect
+	(progn
+	  (reset-buffer filebuf)
+	  (select-frame frame)
+	  (let ((window-min-height 1))
+	    ;; #### should be 2 not 3, but that causes
+	    ;; "window too small to split" errors for some
+	    ;; people (but not for me ...) There's a more
+	    ;; fundamental bug somewhere.
+	    (split-window nil (- (frame-height frame) 3)))
+	  (if file-p
+	      (progn
+		(split-window-horizontally 16)
+		(setq filewin (frame-rightmost-window frame)
+		      dirwin (frame-leftmost-window frame))
+		(set-window-buffer filewin filebuf)
+		(set-window-buffer dirwin dirbuff))
+	    (setq filewin (frame-highest-window frame))
+	    (set-window-buffer filewin filebuf))
+	  (setq user-data (list filebuf dirbuff filewin dirwin))
+	  (set-window-buffer (frame-lowest-window frame) butbuff)
+	  (set-buffer butbuff)
+	  (when (featurep 'scrollbar)
+	    (set-specifier scrollbar-width 0 butbuff))
+	  (insert "                 ")
+	  (insert-gui-button (make-gui-button "OK" 
+					      (lambda (foo)
+						(exit-minibuffer))))
+	  (insert "                 ")
+	  (insert-gui-button (make-gui-button "Cancel"
+					      (lambda (foo)
+						(abort-recursive-edit))))
+	  (let ((rfhookfun
+		 (lambda ()
+		   (if (not file-p)
+		       (mouse-directory-display-completion-list
+			filewin dir (current-buffer) user-data)
+		     (mouse-file-display-completion-list filewin dir
+							 (current-buffer)
+							 user-data)
+		     (mouse-directory-display-completion-list dirwin dir
+							      (current-buffer)
+							      user-data))
+		   (set
+		    (make-local-variable
+		     'completion-display-completion-list-function)
+		    #'(lambda (completions)
+			(display-completion-list
+			 completions
+			 :help-string ""
+			 :activate-callback
+			 'mouse-read-file-name-activate-callback
+			 :user-data user-data)))
+		   ;; kludge!
+		   (remove-hook 'minibuffer-setup-hook rfhookfun)
+		   ))
+		(rfcshookfun
+		 ;; kludge!
+		 ;; #### I really need to flesh out the object
+		 ;; hierarchy better to avoid these kludges.
+		 (lambda ()
+		   (save-excursion
+		     (set-buffer standard-output)
+		     (setq truncate-lines t)))))
+	    (unwind-protect
+		(progn
+		  (add-hook 'minibuffer-setup-hook rfhookfun)
+		  (add-hook 'completion-setup-hook rfcshookfun)
+		  (read-file-name-2 history prompt dir default 
+				    must-match initial-contents
+				    completer))
+	      (remove-hook 'minibuffer-setup-hook rfhookfun)
+	      (remove-hook 'completion-setup-hook rfcshookfun))))
+      (delete-frame frame)
+      (kill-buffer filebuf)
+      (kill-buffer butbuff)
+      (and dirbuff (kill-buffer dirbuff)))))
+
+(defun read-face (prompt &optional must-match)
+  "Read the name of a face from the minibuffer and return it as a symbol."
+  (intern (completing-read prompt obarray 'find-face must-match)))
+
+;; #### - wrong place for this variable?  Exactly.  We probably want
+;; `color-list' to be a console method, so `tty-color-list' becomes
+;; obsolete, and `read-color-completion-table' conses (mapcar #'list
+;; (color-list)), optionally caching the results.
+
+;; Ben wanted all of the possibilities from the `configure' script used
+;; here, but I think this is way too many.  I already trimmed the R4 variants
+;; and a few obvious losers from the list.  --Stig  
+(defvar x-library-search-path '("/usr/X11R6/lib/X11/"
+				"/usr/X11R5/lib/X11/"
+				"/usr/lib/X11R6/X11/"
+				"/usr/lib/X11R5/X11/"
+				"/usr/local/X11R6/lib/X11/"
+				"/usr/local/X11R5/lib/X11/"
+				"/usr/local/lib/X11R6/X11/"
+				"/usr/local/lib/X11R5/X11/"
+				"/usr/X11/lib/X11/"
+				"/usr/lib/X11/"
+				"/usr/local/lib/X11/"
+				"/usr/X386/lib/X11/"
+				"/usr/x386/lib/X11/"
+				"/usr/XFree86/lib/X11/"
+				"/usr/unsupported/lib/X11/"
+				"/usr/athena/lib/X11/"
+				"/usr/local/x11r5/lib/X11/"
+				"/usr/lpp/Xamples/lib/X11/"
+				"/usr/openwin/lib/X11/"
+				"/usr/openwin/share/lib/X11/")
+  "Search path used by `read-color' to find rgb.txt.")
+
+(defvar x-read-color-completion-table)
+
+(defun read-color-completion-table ()
+  (case (device-type)
+    ;; #### Evil device-type dependency
+    (x
+     (if (boundp 'x-read-color-completion-table)
+	 x-read-color-completion-table
+       (let ((rgb-file (locate-file "rgb.txt" x-library-search-path))
+	     clist color p)
+	 (if (not rgb-file)
+	     ;; prevents multiple searches for rgb.txt if we can't find it
+	     (setq x-read-color-completion-table nil)
+	   (with-current-buffer (get-buffer-create " *colors*")
+	     (reset-buffer (current-buffer))
+	     (insert-file-contents rgb-file)
+	     (while (not (eobp))
+	       ;; skip over comments
+	       (while (looking-at "^!")
+		 (end-of-line)
+		 (forward-char 1))
+	       (skip-chars-forward "0-9 \t")
+	       (setq p (point))
+	       (end-of-line)
+	       (setq color (buffer-substring p (point))
+		     clist (cons (list color) clist))
+	       ;; Ugh.  If we want to be able to complete the lowercase form
+	       ;; of the color name, we need to add it twice!  Yuck.
+	       (let ((dcase (downcase color)))
+		 (or (string= dcase color)
+		     (push (list dcase) clist)))
+	       (forward-char 1))
+	     (kill-buffer (current-buffer))))
+	 (setq x-read-color-completion-table clist)
+	 x-read-color-completion-table)))
+    (tty
+     (mapcar #'list (tty-color-list)))))
+
+(defun read-color (prompt &optional must-match initial-contents)
+  "Read the name of a color from the minibuffer.
+On X devices, this uses `x-library-search-path' to find rgb.txt in order
+ to build a completion table.
+On TTY devices, this uses `tty-color-list'."
+  (let ((table (read-color-completion-table)))
+    (completing-read prompt table nil (and table must-match)
+		     initial-contents)))
+
+
+;; #### The doc string for read-non-nil-coding system gets lost if we
+;; only include these if the mule feature is present.  Strangely,
+;; read-coding-system doesn't.
+
+;;(if (featurep 'mule)
+
+(defun read-coding-system (prompt)
+  "Read a coding-system (or nil) from the minibuffer.
+Prompting with string PROMPT."
+  (intern (completing-read prompt obarray 'find-coding-system t)))
+
+(defun read-non-nil-coding-system (prompt)
+  "Read a non-nil coding-system from the minibuffer.
+Prompt with string PROMPT."
+  (let ((retval (intern "")))
+    (while (= 0 (length (symbol-name retval)))
+      (setq retval (intern (completing-read prompt obarray
+					    'find-coding-system
+					    t))))
+    retval))
+
+;;) ;; end of (featurep 'mule)
+
+
+
+(defcustom force-dialog-box-use nil
+  "*If non-nil, always use a dialog box for asking questions, if possible.
+You should *bind* this, not set it.  This is useful if you're doing
+something mousy but which wasn't actually invoked using the mouse."
+  :type 'boolean
+  :group 'minibuffer)
+
+;; We include this here rather than dialog.el so it is defined
+;; even when dialog boxes are not present.
+(defun should-use-dialog-box-p ()
+  "If non-nil, questions should be asked with a dialog box instead of the
+minibuffer.  This looks at `last-command-event' to see if it was a mouse
+event, and checks whether dialog-support exists and the current device
+supports dialog boxes.
+
+The dialog box is totally disabled if the variable `use-dialog-box'
+is set to nil."
+  (and (featurep 'dialog)
+       (device-on-window-system-p)
+       use-dialog-box
+       (or force-dialog-box-use
+	   (button-press-event-p last-command-event)
+	   (button-release-event-p last-command-event)
+	   (misc-user-event-p last-command-event))))
+
+;;; minibuf.el ends here