(dired-get-filename)<declare-function>:
[bpt/emacs.git] / lisp / simple.el
index 386de77..07ac2cc 100644 (file)
@@ -1,7 +1,7 @@
 ;;; simple.el --- basic editing commands for Emacs
 
 ;; Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-;;   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+;;   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
 ;;   Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
@@ -78,19 +78,22 @@ If BUFFER is non-nil, ignore occurrences of that buffer in LIST."
     (car list)))
 
 (defun last-buffer (&optional buffer visible-ok frame)
-  "Return the last non-hidden displayable buffer in the buffer list.
-If BUFFER is non-nil, last-buffer will ignore that buffer.
+  "Return the last buffer in FRAME's buffer list.
+If BUFFER is the last buffer, return the preceding buffer instead.
 Buffers not visible in windows are preferred to visible buffers,
 unless optional argument VISIBLE-OK is non-nil.
-If the optional third argument FRAME is non-nil, use that frame's
-buffer list instead of the selected frame's buffer list.
-If no other buffer exists, the buffer `*scratch*' is returned."
+Optional third argument FRAME nil or omitted means use the
+selected frame's buffer list.
+If no such buffer exists, return the buffer `*scratch*', creating
+it if necessary."
   (setq frame (or frame (selected-frame)))
   (or (get-next-valid-buffer (nreverse (buffer-list frame))
                             buffer visible-ok frame)
-      (progn
-       (set-buffer-major-mode (get-buffer-create "*scratch*"))
-       (get-buffer "*scratch*"))))
+      (get-buffer "*scratch*")
+      (let ((scratch (get-buffer-create "*scratch*")))
+       (set-buffer-major-mode scratch)
+       scratch)))
+
 (defun next-buffer ()
   "Switch to the next buffer in cyclic order."
   (interactive)
@@ -180,9 +183,16 @@ of the errors before moving.
 Major modes providing compile-like functionality should set this variable
 to indicate to `next-error' that this is a candidate buffer and how
 to navigate in it.")
-
 (make-variable-buffer-local 'next-error-function)
 
+(defvar next-error-move-function nil
+  "Function to use to move to an error locus.
+It takes two arguments, a buffer position in the error buffer
+and a buffer position in the error locus buffer.
+The buffer for the error locus should already be current.
+nil means use goto-char using the second argument position.")
+(make-variable-buffer-local 'next-error-move-function)
+
 (defsubst next-error-buffer-p (buffer
                               &optional avoid-current
                               extra-test-inclusive
@@ -358,7 +368,7 @@ select the source buffer."
   (interactive "p")
   (next-error-no-select (- (or n 1))))
 
-;;; Internal variable for `next-error-follow-mode-post-command-hook'.
+;; Internal variable for `next-error-follow-mode-post-command-hook'.
 (defvar next-error-follow-last-line nil)
 
 (define-minor-mode next-error-follow-minor-mode
@@ -372,8 +382,8 @@ location."
     (add-hook 'post-command-hook 'next-error-follow-mode-post-command-hook nil t)
     (make-local-variable 'next-error-follow-last-line)))
 
-;;; Used as a `post-command-hook' by `next-error-follow-mode'
-;;; for the *Compilation* *grep* and *Occur* buffers.
+;; Used as a `post-command-hook' by `next-error-follow-mode'
+;; for the *Compilation* *grep* and *Occur* buffers.
 (defun next-error-follow-mode-post-command-hook ()
   (unless (equal next-error-follow-last-line (line-number-at-pos))
     (setq next-error-follow-last-line (line-number-at-pos))
@@ -415,7 +425,8 @@ Other major modes are defined by comparison with this one."
 
 ;; Making and deleting lines.
 
-(defvar hard-newline (propertize "\n" 'hard t 'rear-nonsticky '(hard)))
+(defvar hard-newline (propertize "\n" 'hard t 'rear-nonsticky '(hard))
+  "Propertized string representing a hard newline character.")
 
 (defun newline (&optional arg)
   "Insert a newline, and move to left margin of the new line if it's blank.
@@ -460,8 +471,8 @@ than the value of `fill-column' and ARG is nil."
        (beforepos (point)))
     (if flag (backward-char 1))
     ;; Call self-insert so that auto-fill, abbrev expansion etc. happens.
-    ;; Set last-command-char to tell self-insert what to insert.
-    (let ((last-command-char ?\n)
+    ;; Set last-command-event to tell self-insert what to insert.
+    (let ((last-command-event ?\n)
          ;; Don't auto-fill if we have a numeric argument.
          ;; Also not if flag is true (it would fill wrong line);
          ;; there is no need to since we're at BOL.
@@ -686,11 +697,14 @@ In binary overwrite mode, this function does overwrite, and octal
 digits are interpreted as a character code.  This is intended to be
 useful for editing binary files."
   (interactive "*p")
-  (let* ((char (let (translation-table-for-input input-method-function)
-                (if (or (not overwrite-mode)
-                        (eq overwrite-mode 'overwrite-mode-binary))
-                    (read-quoted-char)
-                  (read-char)))))
+  (let* ((char
+         ;; Avoid "obsolete" warnings for translation-table-for-input.
+         (with-no-warnings
+           (let (translation-table-for-input input-method-function)
+             (if (or (not overwrite-mode)
+                     (eq overwrite-mode 'overwrite-mode-binary))
+                 (read-quoted-char)
+               (read-char))))))
     ;; This used to assume character codes 0240 - 0377 stand for
     ;; characters in some single-byte character set, and converted them
     ;; to Emacs characters.  But in 23.1 this feature is deprecated
@@ -841,12 +855,15 @@ that uses or sets the mark."
   "Goto LINE, counting from line 1 at beginning of buffer.
 Normally, move point in the current buffer, and leave mark at the
 previous position.  With just \\[universal-argument] as argument,
-move point in the most recently selected other buffer, and switch
-to it.  When called from Lisp code, the optional argument BUFFER
-specifies a buffer to switch to.
+move point in the most recently selected other buffer, and switch to it.
+
+If there's a number in the buffer at point, it is the default for LINE.
 
-If there's a number in the buffer at point, it is the default for
-LINE."
+This function is usually the wrong thing to use in a Lisp program.
+What you probably want instead is something like:
+  (goto-char (point-min)) (forward-line (1- N))
+If at all possible, an even better solution is to use char counts
+rather than line counts."
   (interactive
    (if (and current-prefix-arg (not (consp current-prefix-arg)))
        (list (prefix-numeric-value current-prefix-arg))
@@ -886,7 +903,7 @@ LINE."
   ;; Move to the specified line number in that buffer.
   (save-restriction
     (widen)
-    (goto-char 1)
+    (goto-char (point-min))
     (if (eq selective-display t)
        (re-search-forward "[\n\C-m]" nil 'end (1- line))
       (forward-line (1- line)))))
@@ -983,7 +1000,7 @@ in *Help* buffer.  See also the command `describe-char'."
            encoded encoding-msg display-prop under-display)
        (if (or (not coding)
                (eq (coding-system-type coding) t))
-           (setq coding default-buffer-file-coding-system))
+           (setq coding (default-value 'buffer-file-coding-system)))
        (if (eq (char-charset char) 'eight-bit)
            (setq encoding-msg
                  (format "(%d, #o%o, #x%x, raw-byte)" char char char))
@@ -1044,6 +1061,11 @@ in *Help* buffer.  See also the command `describe-char'."
 (defvar minibuffer-completing-symbol nil
   "Non-nil means completing a Lisp symbol in the minibuffer.")
 
+(defvar minibuffer-default nil
+  "The current default value or list of default values in the minibuffer.
+The functions `read-from-minibuffer' and `completing-read' bind
+this variable locally.")
+
 (defcustom eval-expression-print-level 4
   "Value for `print-level' while printing value in `eval-expression'.
 A value of nil means no limit."
@@ -1088,9 +1110,11 @@ display the result of expression evaluation."
                        &optional eval-expression-insert-value)
   "Evaluate EVAL-EXPRESSION-ARG and print value in the echo area.
 Value is also consed on to front of the variable `values'.
-Optional argument EVAL-EXPRESSION-INSERT-VALUE, if non-nil, means
-insert the result into the current buffer instead of printing it in
-the echo area.
+Optional argument EVAL-EXPRESSION-INSERT-VALUE non-nil (interactively,
+with prefix argument) means insert the result into the current buffer
+instead of printing it in the echo area.  Truncates long output
+according to the value of the variables `eval-expression-print-length'
+and `eval-expression-print-level'.
 
 If `eval-expression-debug-on-error' is non-nil, which is the default,
 this command arranges for all errors to enter the debugger."
@@ -1347,7 +1371,6 @@ this by calling a function defined by `minibuffer-default-add-function'.")
   "Return a list of all completions without the default value.
 This function is used to add all elements of the completion table to
 the end of the list of defaults just after the default value."
-  (interactive)
   (let ((def minibuffer-default)
        (all (all-completions ""
                              minibuffer-completion-table
@@ -1589,7 +1612,7 @@ Go to the history element by the absolute history position HIST-POS."
 
 \f
 ;Put this on C-x u, so we can force that rather than C-_ into startup msg
-(defalias 'advertised-undo 'undo)
+(define-obsolete-function-alias 'advertised-undo 'undo "23.2")
 
 (defconst undo-equiv-table (make-hash-table :test 'eq :weakness t)
   "Table mapping redo records to the corresponding undo one.
@@ -1670,9 +1693,13 @@ as an argument limits undo to changes within the current region."
     ;; In the ordinary case (not within a region), map the redo
     ;; record to the following undos.
     ;; I don't know how to do that in the undo-in-region case.
-    (puthash buffer-undo-list
-            (if undo-in-region t pending-undo-list)
-            undo-equiv-table)
+    (let ((list buffer-undo-list))
+      ;; Strip any leading undo boundaries there might be, like we do
+      ;; above when checking.
+      (while (eq (car list) nil)
+       (setq list (cdr list)))
+      (puthash list (if undo-in-region t pending-undo-list)
+              undo-equiv-table))
     ;; Don't specify a position in the undo record for the undo command.
     ;; Instead, undoing this should move point to where the change is.
     (let ((tail buffer-undo-list)
@@ -1964,7 +1991,8 @@ If you did not execute any such command, the situation is
 probably due to a bug and you should report it.
 
 You can disable the popping up of this buffer by adding the entry
-\(undo discard-info) to the user option `warning-suppress-types'.\n")
+\(undo discard-info) to the user option `warning-suppress-types',
+which is defined in the `warnings' library.\n")
                     :warning)
     (setq buffer-undo-list nil)
     t))
@@ -1985,9 +2013,10 @@ is run interactively.  A value of nil means that output to stderr and
 stdout will be intermixed in the output stream.")
 
 (declare-function mailcap-file-default-commands "mailcap" (files))
+(declare-function dired-get-filename "dired" (&optional localp no-error-if-not-filep))
 
 (defun minibuffer-default-add-shell-commands ()
-  "Return a list of all commands associted with the current file.
+  "Return a list of all commands associated with the current file.
 This function is used to add all related commands retrieved by `mailcap'
 to the end of the list of defaults just after the default value."
   (interactive)
@@ -2038,6 +2067,23 @@ to `shell-command-history'."
           (or hist 'shell-command-history)
           args)))
 
+(defun async-shell-command (command &optional output-buffer error-buffer)
+  "Execute string COMMAND asynchronously in background.
+
+Like `shell-command' but if COMMAND doesn't end in ampersand, adds `&'
+surrounded by whitespace and executes the command asynchronously.
+The output appears in the buffer `*Async Shell Command*'."
+  (interactive
+   (list
+    (read-shell-command "Async shell command: " nil nil
+                       (and buffer-file-name
+                            (file-relative-name buffer-file-name)))
+    current-prefix-arg
+    shell-command-default-error-buffer))
+  (unless (string-match "&[ \t]*\\'" command)
+    (setq command (concat command " &")))
+  (shell-command command output-buffer error-buffer))
+
 (defun shell-command (command &optional output-buffer error-buffer)
   "Execute string COMMAND in inferior shell; display output, if any.
 With prefix argument, insert the COMMAND's output at point.
@@ -2091,8 +2137,12 @@ specifies the value of ERROR-BUFFER."
   (interactive
    (list
     (read-shell-command "Shell command: " nil nil
-                       (and buffer-file-name
-                            (file-relative-name buffer-file-name)))
+                       (let ((filename
+                              (cond
+                               (buffer-file-name)
+                               ((eq major-mode 'dired-mode)
+                                (dired-get-filename nil t)))))
+                         (and filename (file-relative-name filename))))
     current-prefix-arg
     shell-command-default-error-buffer))
   ;; Look for a handler in case default-directory is a remote file name.
@@ -2171,7 +2221,11 @@ specifies the value of ERROR-BUFFER."
                  (setq mode-line-process '(":%s"))
                  (require 'shell) (shell-mode)
                  (set-process-sentinel proc 'shell-command-sentinel)
+                 ;; Use the comint filter for proper handling of carriage motion
+                 ;; (see `comint-inhibit-carriage-motion'),.
+                 (set-process-filter proc 'comint-output-filter)
                  ))
+           ;; Otherwise, command is executed synchronously.
            (shell-command-on-region (point) (point) command
                                     output-buffer nil error-buffer)))))))
 
@@ -2470,6 +2524,17 @@ value passed."
       (when stderr-file (delete-file stderr-file))
       (when lc (delete-file lc)))))
 
+(defvar process-file-side-effects t
+  "Whether a call of `process-file' changes remote files.
+
+Per default, this variable is always set to `t', meaning that a
+call of `process-file' could potentially change any file on a
+remote host.  When set to `nil', a file handler could optimize
+its behaviour with respect to remote file attributes caching.
+
+This variable should never be changed by `setq'.  Instead of, it
+shall be set only by let-binding.")
+
 (defun start-file-process (name buffer program &rest program-args)
   "Start a program in a subprocess.  Return the process object for it.
 
@@ -2482,7 +2547,8 @@ In the latter case, the local part of `default-directory' becomes
 the working directory of the process.
 
 PROGRAM and PROGRAM-ARGS might be file names.  They are not
-objects of file handler invocation."
+objects of file handler invocation.  File handlers might not
+support pty association, if PROGRAM is nil."
   (let ((fh (find-file-name-handler default-directory 'start-file-process)))
     (if fh (apply fh 'start-file-process name buffer program program-args)
       (apply 'start-process name buffer program program-args))))
@@ -2588,9 +2654,9 @@ These commands include \\[set-mark-command] and \\[start-kbd-macro]."
   "Part of the numeric argument for the next command.
 \\[universal-argument] following digits or minus sign ends the argument."
   (interactive "P")
-  (let* ((char (if (integerp last-command-char)
-                  last-command-char
-                (get last-command-char 'ascii-character)))
+  (let* ((char (if (integerp last-command-event)
+                  last-command-event
+                (get last-command-event 'ascii-character)))
         (digit (- (logand char ?\177) ?0)))
     (cond ((integerp arg)
           (setq prefix-arg (+ (* arg 10)
@@ -2740,6 +2806,23 @@ ring directly.")
 (defvar kill-ring-yank-pointer nil
   "The tail of the kill ring whose car is the last thing yanked.")
 
+(defcustom save-interprogram-paste-before-kill nil
+  "Save the paste strings into `kill-ring' before replacing it with emacs strings.
+When one selects something in another program to paste it into Emacs,
+but kills something in Emacs before actually pasting it,
+this selection is gone unless this variable is non-nil,
+in which case the other program's selection is saved in the `kill-ring'
+before the Emacs kill and one can still paste it using \\[yank] \\[yank-pop]."
+  :type 'boolean
+  :group 'killing
+  :version "23.2")
+
+(defcustom kill-do-not-save-duplicates nil
+  "Do not add a new string to `kill-ring' when it is the same as the last one."
+  :type 'boolean
+  :group 'killing
+  :version "23.2")
+
 (defun kill-new (string &optional replace yank-handler)
   "Make STRING the latest kill in the kill ring.
 Set `kill-ring-yank-pointer' to point to it.
@@ -2752,6 +2835,10 @@ inserted into a buffer; see `insert-for-yank' for details.
 When a yank handler is specified, STRING must be non-empty (the yank
 handler, if non-nil, is stored as a `yank-handler' text property on STRING).
 
+When `save-interprogram-paste-before-kill' and `interprogram-paste-function'
+are non-nil, saves the interprogram paste string(s) into `kill-ring' before
+STRING.
+
 When the yank handler has a non-nil PARAM element, the original STRING
 argument is not used by `insert-for-yank'.  However, since Lisp code
 may access and use elements from the kill ring directly, the STRING
@@ -2763,8 +2850,19 @@ argument should still be a \"useful\" string for such uses."
     (if yank-handler
        (signal 'args-out-of-range
                (list string "yank-handler specified for empty string"))))
+  (when (and kill-do-not-save-duplicates
+             (equal string (car kill-ring)))
+    (setq replace t))
   (if (fboundp 'menu-bar-update-yank-menu)
       (menu-bar-update-yank-menu string (and replace (car kill-ring))))
+  (when save-interprogram-paste-before-kill
+    (let ((interprogram-paste (and interprogram-paste-function
+                                   (funcall interprogram-paste-function))))
+      (when interprogram-paste
+        (if (listp interprogram-paste)
+            (dolist (s (nreverse interprogram-paste))
+              (push s kill-ring))
+            (push interprogram-paste kill-ring)))))
   (if (and replace kill-ring)
       (setcar kill-ring string)
     (push string kill-ring)
@@ -2935,9 +3033,9 @@ This command is similar to `copy-region-as-kill', except that it gives
 visual feedback indicating the extent of the region being copied."
   (interactive "r")
   (copy-region-as-kill beg end)
-  ;; This use of interactive-p is correct
+  ;; This use of called-interactively-p is correct
   ;; because the code it controls just gives the user visual feedback.
-  (if (interactive-p)
+  (if (called-interactively-p 'interactive)
       (let ((other-end (if (= (point) beg) end beg))
            (opoint (point))
            ;; Inhibit quitting so we can make a quit here
@@ -3086,13 +3184,13 @@ With ARG, rotate that many kills forward (or backward, if negative)."
 (defun kill-forward-chars (arg)
   (if (listp arg) (setq arg (car arg)))
   (if (eq arg '-) (setq arg -1))
-  (kill-region (point) (forward-point arg)))
+  (kill-region (point) (+ (point) arg)))
 
 ;; Internal subroutine of backward-delete-char
 (defun kill-backward-chars (arg)
   (if (listp arg) (setq arg (car arg)))
   (if (eq arg '-) (setq arg -1))
-  (kill-region (point) (forward-point (- arg))))
+  (kill-region (point) (- (point) arg)))
 
 (defcustom backward-delete-char-untabify-method 'untabify
   "The method for untabifying when deleting backward.
@@ -3139,8 +3237,10 @@ and KILLP is t if a prefix arg was specified."
 Case is ignored if `case-fold-search' is non-nil in the current buffer.
 Goes backward if ARG is negative; error if CHAR not found."
   (interactive "p\ncZap to char: ")
-  (if (char-table-p translation-table-for-input)
-      (setq char (or (aref translation-table-for-input char) char)))
+  ;; Avoid "obsolete" warnings for translation-table-for-input.
+  (with-no-warnings
+    (if (char-table-p translation-table-for-input)
+       (setq char (or (aref translation-table-for-input char) char))))
   (kill-region (point) (progn
                         (search-forward (char-to-string char) nil nil arg)
 ;                       (goto-char (if (> arg 0) (1- (point)) (1+ (point))))
@@ -3211,6 +3311,7 @@ If ARG is negative, kill backward.  Also kill the preceding newline.
 \(This is meant to make \\[repeat] work well with negative arguments.\)
 If ARG is zero, kill current line but exclude the trailing newline."
   (interactive "p")
+  (or arg (setq arg 1))
   (if (and (> arg 0) (eobp) (save-excursion (forward-visible-line 0) (eobp)))
       (signal 'end-of-buffer nil))
   (if (and (< arg 0) (bobp) (save-excursion (end-of-visible-line) (bobp)))
@@ -3412,7 +3513,7 @@ START and END specify the portion of the current buffer to be copied."
        (insert-buffer-substring oldbuf start end)))))
 \f
 (put 'mark-inactive 'error-conditions '(mark-inactive error))
-(put 'mark-inactive 'error-message "The mark is not active now")
+(put 'mark-inactive 'error-message (purecopy "The mark is not active now"))
 
 (defvar activate-mark-hook nil
   "Hook run when the mark becomes active.
@@ -3436,16 +3537,33 @@ a mistake; see the documentation of `set-mark'."
       (marker-position (mark-marker))
     (signal 'mark-inactive nil)))
 
+(defcustom select-active-regions nil
+  "If non-nil, an active region automatically becomes the window selection."
+  :type 'boolean
+  :group 'killing
+  :version "23.1")
+
 ;; Many places set mark-active directly, and several of them failed to also
 ;; run deactivate-mark-hook.  This shorthand should simplify.
-(defsubst deactivate-mark ()
+(defsubst deactivate-mark (&optional force)
   "Deactivate the mark by setting `mark-active' to nil.
-\(That makes a difference only in Transient Mark mode.)
-Also runs the hook `deactivate-mark-hook'."
-  (when transient-mark-mode
-    (if (or (eq transient-mark-mode 'lambda)
-           (and (eq (car-safe transient-mark-mode) 'only)
-                (null (cdr transient-mark-mode))))
+Unless FORCE is non-nil, this function does nothing if Transient
+Mark mode is disabled.
+This function also runs `deactivate-mark-hook'."
+  (when (or transient-mark-mode force)
+    ;; Copy the latest region into the primary selection, if desired.
+    (and select-active-regions
+        mark-active
+        (display-selections-p)
+        (x-selection-owner-p 'PRIMARY)
+        (x-set-selection 'PRIMARY (buffer-substring-no-properties
+                                   (region-beginning) (region-end))))
+    (if (and (null force)
+            (or (eq transient-mark-mode 'lambda)
+                (and (eq (car-safe transient-mark-mode) 'only)
+                     (null (cdr transient-mark-mode)))))
+       ;; When deactivating a temporary region, don't change
+       ;; `mark-active' or run `deactivate-mark-hook'.
        (setq transient-mark-mode nil)
       (if (eq (car-safe transient-mark-mode) 'only)
          (setq transient-mark-mode (cdr transient-mark-mode)))
@@ -3457,13 +3575,10 @@ Also runs the hook `deactivate-mark-hook'."
   (when (mark t)
     (setq mark-active t)
     (unless transient-mark-mode
-      (setq transient-mark-mode 'lambda))))
-
-(defcustom select-active-regions nil
-  "If non-nil, an active region automatically becomes the window selection."
-  :type 'boolean
-  :group 'killing
-  :version "23.1")
+      (setq transient-mark-mode 'lambda))
+    (when (and select-active-regions
+              (display-selections-p))
+      (x-set-selection 'PRIMARY (current-buffer)))))
 
 (defun set-mark (pos)
   "Set this buffer's mark to POS.  Don't use this function!
@@ -3486,15 +3601,14 @@ store it in a Lisp variable.  Example:
       (progn
        (setq mark-active t)
        (run-hooks 'activate-mark-hook)
-       (and select-active-regions
-            (x-set-selection
-             nil (buffer-substring (region-beginning) (region-end))))
+       (when (and select-active-regions
+                  (display-selections-p))
+         (x-set-selection 'PRIMARY (current-buffer)))
        (set-marker (mark-marker) pos (current-buffer)))
     ;; Normally we never clear mark-active except in Transient Mark mode.
-    ;; But when we actually clear out the mark value too,
-    ;; we must clear mark-active in any mode.
-    (setq mark-active nil)
-    (run-hooks 'deactivate-mark-hook)
+    ;; But when we actually clear out the mark value too, we must
+    ;; clear mark-active in any mode.
+    (deactivate-mark t)
     (set-marker (mark-marker) nil)))
 
 (defcustom use-empty-active-region nil
@@ -3513,23 +3627,25 @@ point otherwise."
 (defun use-region-p ()
   "Return t if the region is active and it is appropriate to act on it.
 This is used by commands that act specially on the region under
-Transient Mark mode.  It returns t if and only if Transient Mark
-mode is enabled, the mark is active, and the region is non-empty.
-If `use-empty-active-region' is non-nil, it returns t even if the
-region is empty.
+Transient Mark mode.
+
+The return value is t provided Transient Mark mode is enabled and
+the mark is active; and, when `use-empty-active-region' is
+non-nil, provided the region is empty.  Otherwise, the return
+value is nil.
 
-For some commands, it may be appropriate to disregard the value
-of `use-empty-active-region'; in that case, use `region-active-p'."
+For some commands, it may be appropriate to ignore the value of
+`use-empty-active-region'; in that case, use `region-active-p'."
   (and (region-active-p)
        (or use-empty-active-region (> (region-end) (region-beginning)))))
 
 (defun region-active-p ()
   "Return t if Transient Mark mode is enabled and the mark is active.
 
-Most commands that act on the region if it is active and
-Transient Mark mode is enabled, and on the text near point
-otherwise, should use `use-region-p' instead.  That function
-checks the value of `use-empty-active-region' as well."
+Some commands act specially on the region when Transient Mark
+mode is enabled.  Usually, such commands should use
+`use-region-p' instead of this function, because `use-region-p'
+also checks the value of `use-empty-active-region'."
   (and transient-mark-mode mark-active))
 
 (defvar mark-ring nil
@@ -3726,31 +3842,46 @@ mode temporarily."
          (t (activate-mark)))
     nil))
 
-(defun handle-shift-selection (&optional deactivate)
-  "Check for shift translation, and operate on the mark accordingly.
-This is called whenever a command with a `^' character in its
-`interactive' spec is invoked while `shift-select-mode' is
-non-nil.
-
-If the command was invoked through shift-translation, set the
-mark and activate the region temporarily, unless it was already
-set in this way.  If the command was invoked without
-shift-translation and a region is temporarily active, deactivate
-the mark.
-
-With optional arg DEACTIVATE, only perform region deactivation."
-  (cond ((and this-command-keys-shift-translated
-             (null deactivate))
-        (unless (and mark-active
-                     (eq (car-safe transient-mark-mode) 'only))
-          (setq transient-mark-mode
-                (cons 'only
-                      (unless (eq transient-mark-mode 'lambda)
-                        transient-mark-mode)))
-          (push-mark nil nil t)))
-       ((eq (car-safe transient-mark-mode) 'only)
-        (setq transient-mark-mode (cdr transient-mark-mode))
-        (deactivate-mark))))
+(defcustom shift-select-mode t
+  "When non-nil, shifted motion keys activate the mark momentarily.
+
+While the mark is activated in this way, any shift-translated point
+motion key extends the region, and if Transient Mark mode was off, it
+is temporarily turned on.  Furthermore, the mark will be deactivated
+by any subsequent point motion key that was not shift-translated, or
+by any action that normally deactivates the mark in Transient Mark mode.
+
+See `this-command-keys-shift-translated' for the meaning of
+shift-translation."
+  :type 'boolean
+  :group 'editing-basics)
+
+(defun handle-shift-selection ()
+  "Activate/deactivate mark depending on invocation thru shift translation.
+This function is called by `call-interactively' when a command
+with a `^' character in its `interactive' spec is invoked, before
+running the command itself.
+
+If `shift-select-mode' is enabled and the command was invoked
+through shift translation, set the mark and activate the region
+temporarily, unless it was already set in this way.  See
+`this-command-keys-shift-translated' for the meaning of shift
+translation.
+
+Otherwise, if the region has been activated temporarily,
+deactivate it, and restore the variable `transient-mark-mode' to
+its earlier value."
+  (cond ((and shift-select-mode this-command-keys-shift-translated)
+         (unless (and mark-active
+                      (eq (car-safe transient-mark-mode) 'only))
+           (setq transient-mark-mode
+                 (cons 'only
+                       (unless (eq transient-mark-mode 'lambda)
+                         transient-mark-mode)))
+           (push-mark nil nil t)))
+        ((eq (car-safe transient-mark-mode) 'only)
+         (setq transient-mark-mode (cdr transient-mark-mode))
+         (deactivate-mark))))
 
 (define-minor-mode transient-mark-mode
   "Toggle Transient Mark mode.
@@ -3775,6 +3906,7 @@ Invoke \\[apropos-documentation] and type \"transient\" or
 commands which are sensitive to the Transient Mark mode."
   :global t
   :init-value (not noninteractive)
+  :initialize 'custom-initialize-delay
   :group 'editing-basics)
 
 ;; The variable transient-mark-mode is ugly: it can take on special
@@ -3867,7 +3999,7 @@ and more reliable (no dependence on goal column, etc.)."
            (end-of-line)
            (insert (if use-hard-newlines hard-newline "\n")))
        (line-move arg nil nil try-vscroll))
-    (if (interactive-p)
+    (if (called-interactively-p 'interactive)
        (condition-case nil
            (line-move arg nil nil try-vscroll)
          ((beginning-of-buffer end-of-buffer) (ding)))
@@ -3897,7 +4029,7 @@ If you are thinking of using this in a Lisp program, consider using
 to use and more reliable (no dependence on goal column, etc.)."
   (interactive "^p\np")
   (or arg (setq arg 1))
-  (if (interactive-p)
+  (if (called-interactively-p 'interactive)
       (condition-case nil
          (line-move (- arg) nil nil try-vscroll)
        ((beginning-of-buffer end-of-buffer) (ding)))
@@ -3922,10 +4054,14 @@ This has no effect when `line-move-visual' is non-nil."
 (defvar temporary-goal-column 0
   "Current goal column for vertical motion.
 It is the column where point was at the start of the current run
-of vertical motion commands.  It is a floating point number when
-moving by visual lines via `line-move-visual'; this is the
-x-position, in pixels, divided by the default column width.  When
-the `track-eol' feature is doing its job, the value is
+of vertical motion commands.
+
+When moving by visual lines via `line-move-visual', it is a cons
+cell (COL . HSCROLL), where COL is the x-position, in pixels,
+divided by the default column width, and HSCROLL is the number of
+columns by which window is scrolled from left margin.
+
+When the `track-eol' feature is doing its job, the value is
 `most-positive-fixnum'.")
 
 (defcustom line-move-ignore-invisible t
@@ -4022,21 +4158,47 @@ into account variable-width characters and line continuation."
 ;; Arg says how many lines to move.  The value is t if we can move the
 ;; specified number of lines.
 (defun line-move-visual (arg &optional noerror)
-  (unless (and (floatp temporary-goal-column)
-              (or (memq last-command '(next-line previous-line))
-                  ;; In case we're called from some other command.
-                  (eq last-command this-command)))
-    (let ((x (car (nth 2 (posn-at-point)))))
-      (when x
-       (setq temporary-goal-column (/ (float x) (frame-char-width))))))
-  (or (= (vertical-motion
-         (cons (or goal-column (truncate temporary-goal-column)) arg))
-        arg)
-      (unless noerror
-       (signal (if (< arg 0)
-                   'beginning-of-buffer
-                 'end-of-buffer)
-               nil))))
+  (let ((opoint (point))
+       (hscroll (window-hscroll))
+       target-hscroll)
+    ;; Check if the previous command was a line-motion command, or if
+    ;; we were called from some other command.
+    (if (and (consp temporary-goal-column)
+            (memq last-command `(next-line previous-line ,this-command)))
+       ;; If so, there's no need to reset `temporary-goal-column',
+       ;; but we may need to hscroll.
+       (if (or (/= (cdr temporary-goal-column) hscroll)
+               (>  (cdr temporary-goal-column) 0))
+           (setq target-hscroll (cdr temporary-goal-column)))
+      ;; Otherwise, we should reset `temporary-goal-column'.
+      (let ((posn (posn-at-point)))
+       (cond
+        ;; Handle the `overflow-newline-into-fringe' case:
+        ((eq (nth 1 posn) 'right-fringe)
+         (setq temporary-goal-column (cons (- (window-width) 1) hscroll)))
+        ((car (posn-x-y posn))
+         (setq temporary-goal-column
+               (cons (/ (float (car (posn-x-y posn)))
+                        (frame-char-width)) hscroll))))))
+    (if target-hscroll
+       (set-window-hscroll (selected-window) target-hscroll))
+    (or (and (= (vertical-motion
+                (cons (or goal-column
+                          (if (consp temporary-goal-column)
+                              (truncate (car temporary-goal-column))
+                            temporary-goal-column))
+                      arg))
+               arg)
+            (or (>= arg 0)
+                (/= (point) opoint)
+                ;; If the goal column lies on a display string,
+                ;; `vertical-motion' advances the cursor to the end
+                ;; of the string.  For arg < 0, this can cause the
+                ;; cursor to get stuck.  (Bug#3020).
+                (= (vertical-motion arg) arg)))
+       (unless noerror
+         (signal (if (< arg 0) 'beginning-of-buffer 'end-of-buffer)
+                 nil)))))
 
 ;; This is the guts of next-line and previous-line.
 ;; Arg says how many lines to move.
@@ -4047,8 +4209,9 @@ into account variable-width characters and line continuation."
   (let ((inhibit-point-motion-hooks t)
        (opoint (point))
        (orig-arg arg))
-    (if (floatp temporary-goal-column)
-       (setq temporary-goal-column (truncate temporary-goal-column)))
+    (if (consp temporary-goal-column)
+       (setq temporary-goal-column (+ (car temporary-goal-column)
+                                      (cdr temporary-goal-column))))
     (unwind-protect
        (progn
          (if (not (memq last-command '(next-line previous-line)))
@@ -4189,7 +4352,7 @@ into account variable-width characters and line continuation."
               (point))))
 
        ;; Move to the desired column.
-       (line-move-to-column column)
+       (line-move-to-column (truncate column))
 
        ;; Corner case: suppose we start out in a field boundary in
        ;; the middle of a continued line.  When we get to
@@ -4290,12 +4453,14 @@ and `current-column' to be able to ignore invisible text."
 
 (defun move-end-of-line (arg)
   "Move point to end of current line as displayed.
-\(If there's an image in the line, this disregards newlines
-which are part of the text that the image rests on.)
-
 With argument ARG not nil or 1, move forward ARG - 1 lines first.
 If point reaches the beginning or end of buffer, it stops there.
-To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
+
+To ignore the effects of the `intangible' text or overlay
+property, bind `inhibit-point-motion-hooks' to t.
+If there is an image in the current line, this function
+disregards newlines that are part of the text on which the image
+rests."
   (interactive "^p")
   (or arg (setq arg 1))
   (let (done)
@@ -4366,8 +4531,8 @@ To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
                                     (/= arg 1) t nil)))))
 
 
-;;; Many people have said they rarely use this feature, and often type
-;;; it by accident.  Maybe it shouldn't even be on a key.
+;; Many people have said they rarely use this feature, and often type
+;; it by accident.  Maybe it shouldn't even be on a key.
 (put 'set-goal-column 'disabled t)
 
 (defun set-goal-column (arg)
@@ -4425,20 +4590,10 @@ To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
 
 (defun kill-visual-line (&optional arg)
   "Kill the rest of the visual line.
-If there are only whitespace characters there, kill through the
-newline as well.
-
-With prefix argument ARG, kill that many lines from point.
-Negative arguments kill lines backward.
-With zero argument, kill the text before point on the current line.
-
-When calling from a program, nil means \"no arg\",
-a number counts as a prefix arg.
-
-If `kill-whole-line' is non-nil, then this command kills the whole line
-including its terminating newline, when used at the beginning of a line
-with no argument.  As a consequence, you can always kill a whole line
-by typing \\[beginning-of-line] \\[kill-line].
+With prefix argument ARG, kill that many visual lines from point.
+If ARG is negative, kill visual lines backward.
+If ARG is zero, kill the text before point on the current visual
+line.
 
 If you want to append the killed line to the last killed text,
 use \\[append-next-kill] before \\[kill-line].
@@ -4449,30 +4604,24 @@ you can use this command to copy text from a read-only buffer.
 \(If the variable `kill-read-only-ok' is non-nil, then this won't
 even beep.)"
   (interactive "P")
+  ;; Like in `kill-line', it's better to move point to the other end
+  ;; of the kill before killing.
   (let ((opoint (point))
-       (line-move-visual t)
-       end)
-    ;; It is better to move point to the other end of the kill before
-    ;; killing.  That way, in a read-only buffer, point moves across
-    ;; the text that is copied to the kill ring.  The choice has no
-    ;; effect on undo now that undo records the value of point from
-    ;; before the command was run.
+       (kill-whole-line (and kill-whole-line (bolp))))
     (if arg
        (vertical-motion (prefix-numeric-value arg))
-      (if (eobp)
-         (signal 'end-of-buffer nil))
-      (setq end (save-excursion
-                 (end-of-visual-line) (point)))
-      (if (or (save-excursion
-               ;; If trailing whitespace is visible,
-               ;; don't treat it as nothing.
-               (unless show-trailing-whitespace
-                 (skip-chars-forward " \t" end))
-               (= (point) end))
-             (and kill-whole-line (bolp)))
-         (line-move 1)
-       (goto-char end)))
-    (kill-region opoint (point))))
+      (end-of-visual-line 1)
+      (if (= (point) opoint)
+         (vertical-motion 1)
+       ;; Skip any trailing whitespace at the end of the visual line.
+       ;; We used to do this only if `show-trailing-whitespace' is
+       ;; nil, but that's wrong; the correct thing would be to check
+       ;; whether the trailing whitespace is highlighted.  But, it's
+       ;; OK to just do this unconditionally.
+       (skip-chars-forward " \t")))
+    (kill-region opoint (if (and kill-whole-line (looking-at "\n"))
+                           (1+ (point))
+                         (point)))))
 
 (defun next-logical-line (&optional arg try-vscroll)
   "Move cursor vertically down ARG lines.
@@ -4504,8 +4653,10 @@ the variable `line-move-visual'."
     (define-key map [remap kill-line] 'kill-visual-line)
     (define-key map [remap move-beginning-of-line] 'beginning-of-visual-line)
     (define-key map [remap move-end-of-line]  'end-of-visual-line)
-    (define-key map "\M-[" 'previous-logical-line)
-    (define-key map "\M-]" 'next-logical-line)
+    ;; These keybindings interfere with xterm function keys.  Are
+    ;; there any other suitable bindings?
+    ;; (define-key map "\M-[" 'previous-logical-line)
+    ;; (define-key map "\M-]" 'next-logical-line)
     map))
 
 (defcustom visual-line-fringe-indicators '(nil nil)
@@ -4706,7 +4857,7 @@ With argument 0, interchanges line point is in with line mark is in."
      ((= arg 0)
       (save-excursion
        (setq pos1 (funcall aux 1))
-       (goto-char (mark))
+       (goto-char (or (mark) (error "No mark set in this buffer")))
        (setq pos2 (funcall aux 1))
        (transpose-subr-1 pos1 pos2))
       (exchange-point-and-mark))
@@ -4967,6 +5118,10 @@ unless optional argument SOFT is non-nil."
 Some major modes set this.")
 
 (put 'auto-fill-function :minor-mode-function 'auto-fill-mode)
+;; `functions' and `hooks' are usually unsafe to set, but setting
+;; auto-fill-function to nil in a file-local setting is safe and
+;; can be useful to prevent auto-filling.
+(put 'auto-fill-function 'safe-local-variable 'null)
 ;; FIXME: turn into a proper minor mode.
 ;; Add a global minor mode version of it.
 (defun auto-fill-mode (&optional arg)
@@ -5063,9 +5218,24 @@ is non-nil."
   (message "Truncate long lines %s"
           (if truncate-lines "enabled" "disabled")))
 
-(defvar overwrite-mode-textual " Ovwrt"
+(defun toggle-word-wrap (&optional arg)
+  "Toggle whether to use word-wrapping for continuation lines.
+With prefix argument ARG, wrap continuation lines at word boundaries
+if ARG is positive, otherwise wrap them at the right screen edge.
+This command toggles the value of `word-wrap'.  It has no effect
+if long lines are truncated."
+  (interactive "P")
+  (setq word-wrap
+       (if (null arg)
+           (not word-wrap)
+         (> (prefix-numeric-value arg) 0)))
+  (force-mode-line-update)
+  (message "Word wrapping %s"
+          (if word-wrap "enabled" "disabled")))
+
+(defvar overwrite-mode-textual (purecopy " Ovwrt")
   "The string displayed in the mode line when in overwrite mode.")
-(defvar overwrite-mode-binary " Bin Ovwrt"
+(defvar overwrite-mode-binary (purecopy " Bin Ovwrt")
   "The string displayed in the mode line when in binary overwrite mode.")
 
 (defun overwrite-mode (arg)
@@ -5151,9 +5321,10 @@ It is also ignored if `show-paren-mode' is enabled."
   :type 'boolean
   :group 'paren-blinking)
 
-(defcustom blink-matching-paren-distance (* 25 1024)
+(defcustom blink-matching-paren-distance (* 100 1024)
   "If non-nil, maximum distance to search backwards for matching open-paren.
 If nil, search stops at the beginning of the accessible portion of the buffer."
+  :version "23.2"                       ; 25->100k
   :type '(choice (const nil) integer)
   :group 'paren-blinking)
 
@@ -5217,13 +5388,17 @@ it skips the contents of comments that end before point."
                  ;; a matching-char info, in which case the two CDRs
                  ;; should match.
                  (eq matching-paren (cdr (syntax-after (1- oldpos))))))
-        (message "Mismatched parentheses"))
+       (if (minibufferp)
+           (minibuffer-message " [Mismatched parentheses]")
+         (message "Mismatched parentheses")))
        ((not blinkpos)
         (or blink-matching-paren-distance
             ;; Don't complain when `$' with no blinkpos, because it
             ;; could just be the first one typed in the buffer.
             atdollar
-            (message "Unmatched parenthesis")))
+            (if (minibufferp)
+               (minibuffer-message " [Unmatched parenthesis]")
+             (message "Unmatched parenthesis"))))
        ((pos-visible-in-window-p blinkpos)
         ;; Matching open within window, temporarily move to blinkpos but only
         ;; if `blink-matching-paren-on-screen' is non-nil.
@@ -5336,7 +5511,7 @@ See also `mail-user-agent' concerning sending mail."
   :version "21.1"
   :group 'mail)
 
-(defcustom mail-user-agent 'sendmail-user-agent
+(defcustom mail-user-agent 'message-user-agent
   "Your preference for a mail composition package.
 Various Emacs Lisp packages (e.g. Reporter) require you to compose an
 outgoing email message.  This variable lets you specify which
@@ -5344,12 +5519,12 @@ mail-sending package you prefer.
 
 Valid values include:
 
-  `sendmail-user-agent' -- use the default Emacs Mail package.
+  `message-user-agent'  -- use the Message package.
+                           See Info node `(message)'.
+  `sendmail-user-agent' -- use the Mail package.
                            See Info node `(emacs)Sending Mail'.
   `mh-e-user-agent'     -- use the Emacs interface to the MH mail system.
                            See Info node `(mh-e)'.
-  `message-user-agent'  -- use the Gnus Message package.
-                           See Info node `(message)'.
   `gnus-user-agent'     -- like `message-user-agent', but with Gnus
                            paraphernalia, particularly the Gcc: header for
                            archiving.
@@ -5359,19 +5534,20 @@ your package for details.  The function should return non-nil if it
 succeeds.
 
 See also `read-mail-command' concerning reading mail."
-  :type '(radio (function-item :tag "Default Emacs mail"
+  :type '(radio (function-item :tag "Message package"
+                              :format "%t\n"
+                              message-user-agent)
+               (function-item :tag "Mail package"
                               :format "%t\n"
                               sendmail-user-agent)
                (function-item :tag "Emacs interface to MH"
                               :format "%t\n"
                               mh-e-user-agent)
-               (function-item :tag "Gnus Message package"
-                              :format "%t\n"
-                              message-user-agent)
-               (function-item :tag "Gnus Message with full Gnus features"
+               (function-item :tag "Message with full Gnus features"
                               :format "%t\n"
                               gnus-user-agent)
                (function :tag "Other"))
+  :version "23.2"                       ; sendmail->message
   :group 'mail)
 
 (define-mail-user-agent 'sendmail-user-agent
@@ -5427,7 +5603,7 @@ header fields.  Elements look like (HEADER . VALUE) where both
 HEADER and VALUE are strings.
 
 CONTINUE, if non-nil, says to continue editing a message already
-being composed.
+being composed.  Interactively, CONTINUE is the prefix argument.
 
 SWITCH-FUNCTION, if non-nil, is a function to use to
 switch to and display the buffer used for mail composition.
@@ -5550,6 +5726,7 @@ With a prefix argument, set VARIABLE to VALUE buffer-locally."
     (define-key map "\e\e\e" 'delete-completion-window)
     (define-key map [left] 'previous-completion)
     (define-key map [right] 'next-completion)
+    (define-key map "q" 'quit-window)
     map)
   "Local map for completion list buffers.")
 
@@ -5566,6 +5743,13 @@ Initial value is nil to avoid some compiler warnings.")
 This also applies to other functions such as `choose-completion'
 and `mouse-choose-completion'.")
 
+(defvar completion-base-position nil
+  "Position of the base of the text corresponding to the shown completions.
+This variable is used in the *Completions* buffers.
+Its value is a list of the form (START END) where START is the place
+where the completion should be inserted and END (if non-nil) is the end
+of the text to replace.  If END is nil, point is used instead.")
+
 (defvar completion-base-size nil
   "Number of chars before point not involved in completion.
 This is a local variable in the completion list buffer.
@@ -5576,6 +5760,7 @@ Only characters in the field at point are included.
 If nil, Emacs determines which part of the tail end of the
 buffer's text is involved in completion by comparing the text
 directly.")
+(make-obsolete-variable 'completion-base-size 'completion-base-position "23.2")
 
 (defun delete-completion-window ()
   "Delete the completion list window.
@@ -5622,54 +5807,82 @@ With prefix argument N, move N items (negative N means move backward)."
                    (point) 'mouse-face nil beg))
        (setq n (1+ n))))))
 
-(defun choose-completion ()
-  "Choose the completion that point is in or next to."
-  (interactive)
-  (let (beg end completion (buffer completion-reference-buffer)
-       (base-size completion-base-size))
-    (if (and (not (eobp)) (get-text-property (point) 'mouse-face))
-       (setq end (point) beg (1+ (point))))
-    (if (and (not (bobp)) (get-text-property (1- (point)) 'mouse-face))
-       (setq end (1- (point)) beg (point)))
-    (if (null beg)
-       (error "No completion here"))
-    (setq beg (previous-single-property-change beg 'mouse-face))
-    (setq end (or (next-single-property-change end 'mouse-face) (point-max)))
-    (setq completion (buffer-substring-no-properties beg end))
+(defun choose-completion (&optional event)
+  "Choose the completion at point."
+  (interactive (list last-nonmenu-event))
+  ;; In case this is run via the mouse, give temporary modes such as
+  ;; isearch a chance to turn off.
+  (run-hooks 'mouse-leave-buffer-hook)
+  (let (buffer base-size base-position choice)
+    (with-current-buffer (window-buffer (posn-window (event-start event)))
+      (setq buffer completion-reference-buffer)
+      (setq base-size completion-base-size)
+      (setq base-position completion-base-position)
+      (save-excursion
+        (goto-char (posn-point (event-start event)))
+        (let (beg end)
+          (if (and (not (eobp)) (get-text-property (point) 'mouse-face))
+              (setq end (point) beg (1+ (point))))
+          (if (and (not (bobp)) (get-text-property (1- (point)) 'mouse-face))
+              (setq end (1- (point)) beg (point)))
+          (if (null beg)
+              (error "No completion here"))
+          (setq beg (previous-single-property-change beg 'mouse-face))
+          (setq end (or (next-single-property-change end 'mouse-face)
+                        (point-max)))
+          (setq choice (buffer-substring-no-properties beg end)))))
+
     (let ((owindow (selected-window)))
+      (select-window (posn-window (event-start event)))
       (if (and (one-window-p t 'selected-frame)
-              (window-dedicated-p owindow))
+              (window-dedicated-p (selected-window)))
          ;; This is a special buffer's frame
          (iconify-frame (selected-frame))
        (or (window-dedicated-p (selected-window))
            (bury-buffer)))
       (select-window
        (or (and (buffer-live-p buffer)
-               (get-buffer-window buffer))
+               (get-buffer-window buffer 0))
           owindow)))
-    (choose-completion-string completion buffer base-size)))
+    
+    (choose-completion-string
+     choice buffer
+     (or base-position
+         (when base-size
+           ;; Someone's using old completion code that doesn't know
+           ;; about base-position yet.
+           (list (+ base-size (with-current-buffer buffer (field-beginning)))))
+         ;; If all else fails, just guess.
+         (with-current-buffer buffer
+           (list (choose-completion-guess-base-position choice)))))))
 
 ;; Delete the longest partial match for STRING
 ;; that can be found before POINT.
+(defun choose-completion-guess-base-position (string)
+  (save-excursion
+    (let ((opoint (point))
+          len)
+      ;; Try moving back by the length of the string.
+      (goto-char (max (- (point) (length string))
+                      (minibuffer-prompt-end)))
+      ;; See how far back we were actually able to move.  That is the
+      ;; upper bound on how much we can match and delete.
+      (setq len (- opoint (point)))
+      (if completion-ignore-case
+          (setq string (downcase string)))
+      (while (and (> len 0)
+                  (let ((tail (buffer-substring (point) opoint)))
+                    (if completion-ignore-case
+                        (setq tail (downcase tail)))
+                    (not (string= tail (substring string 0 len)))))
+        (setq len (1- len))
+        (forward-char 1))
+      (point))))
+
 (defun choose-completion-delete-max-match (string)
-  (let ((opoint (point))
-       len)
-    ;; Try moving back by the length of the string.
-    (goto-char (max (- (point) (length string))
-                   (minibuffer-prompt-end)))
-    ;; See how far back we were actually able to move.  That is the
-    ;; upper bound on how much we can match and delete.
-    (setq len (- opoint (point)))
-    (if completion-ignore-case
-       (setq string (downcase string)))
-    (while (and (> len 0)
-               (let ((tail (buffer-substring (point) opoint)))
-                 (if completion-ignore-case
-                     (setq tail (downcase tail)))
-                 (not (string= tail (substring string 0 len)))))
-      (setq len (1- len))
-      (forward-char 1))
-    (delete-char len)))
+  (delete-region (choose-completion-guess-base-position string) (point)))
+(make-obsolete 'choose-completion-delete-max-match
+               'choose-completion-guess-base-position "23.2")
 
 (defvar choose-completion-string-functions nil
   "Functions that may override the normal insertion of a completion choice.
@@ -5687,16 +5900,21 @@ the minibuffer; no further functions will be called.
 If all functions in the list return nil, that means to use
 the default method of inserting the completion in BUFFER.")
 
-(defun choose-completion-string (choice &optional buffer base-size)
+(defun choose-completion-string (choice &optional buffer base-position)
   "Switch to BUFFER and insert the completion choice CHOICE.
-BASE-SIZE, if non-nil, says how many characters of BUFFER's text
-to keep.  If it is nil, we call `choose-completion-delete-max-match'
-to decide what to delete."
+BASE-POSITION, says where to insert the completion."
 
   ;; If BUFFER is the minibuffer, exit the minibuffer
   ;; unless it is reading a file name and CHOICE is a directory,
   ;; or completion-no-auto-exit is non-nil.
 
+  ;; Some older code may call us passing `base-size' instead of
+  ;; `base-position'.  It's difficult to make any use of `base-size',
+  ;; so we just ignore it.
+  (unless (consp base-position)
+    (message "Obsolete `base-size' passed to choose-completion-string")
+    (setq base-position nil))
+
   (let* ((buffer (or buffer completion-reference-buffer))
         (mini-p (minibufferp buffer)))
     ;; If BUFFER is a minibuffer, barf unless it's the currently
@@ -5710,18 +5928,14 @@ to decide what to delete."
       (set-buffer buffer)
       (unless (run-hook-with-args-until-success
               'choose-completion-string-functions
-              choice buffer mini-p base-size)
+               ;; The fourth arg used to be `mini-p' but was useless
+               ;; (since minibufferp can be used on the `buffer' arg)
+               ;; and indeed unused.  The last used to be `base-size', so we
+               ;; keep it to try and avoid breaking old code.
+              choice buffer base-position nil)
        ;; Insert the completion into the buffer where it was requested.
-        ;; FIXME:
-        ;; - There may not be a field at point, or there may be a field but
-        ;;   it's not a "completion field", in which case we have to
-        ;;   call choose-completion-delete-max-match even if base-size is set.
-        ;; - we may need to delete further than (point) to (field-end),
-        ;;   depending on the completion-style, and for that we need to
-        ;;   extra data `completion-extra-size'.
-       (if base-size
-           (delete-region (+ base-size (field-beginning)) (point))
-         (choose-completion-delete-max-match choice))
+        (delete-region (or (car base-position) (point))
+                       (or (cadr base-position) (point)))
        (insert choice)
        (remove-text-properties (- (point) (length choice)) (point)
                                '(mouse-face nil))
@@ -5734,13 +5948,19 @@ to decide what to delete."
             minibuffer-completion-table
             ;; If this is reading a file name, and the file name chosen
             ;; is a directory, don't exit the minibuffer.
-            (if (and minibuffer-completing-file-name
-                     (file-directory-p (field-string (point-max))))
-                (let ((mini (active-minibuffer-window)))
-                  (select-window mini)
-                  (when minibuffer-auto-raise
-                    (raise-frame (window-frame mini))))
-              (exit-minibuffer)))))))
+             (let* ((result (buffer-substring (field-beginning) (point)))
+                    (bounds
+                     (completion-boundaries result minibuffer-completion-table
+                                            minibuffer-completion-predicate
+                                            "")))
+               (if (eq (car bounds) (length result))
+                   ;; The completion chosen leads to a new set of completions
+                   ;; (e.g. it's a directory): don't exit the minibuffer yet.
+                   (let ((mini (active-minibuffer-window)))
+                     (select-window mini)
+                     (when minibuffer-auto-raise
+                       (raise-frame (window-frame mini))))
+                 (exit-minibuffer))))))))
 
 (define-derived-mode completion-list-mode nil "Completion List"
   "Major mode for buffers showing lists of possible completions.
@@ -5769,45 +5989,28 @@ Called from `temp-buffer-show-hook'."
   :version "22.1"
   :group 'completion)
 
-;; This is for packages that need to bind it to a non-default regexp
-;; in order to make the first-differing character highlight work
-;; to their liking
-(defvar completion-root-regexp "^/"
-  "Regexp to use in `completion-setup-function' to find the root directory.")
-
 ;; This function goes in completion-setup-hook, so that it is called
 ;; after the text of the completion list buffer is written.
 (defun completion-setup-function ()
   (let* ((mainbuf (current-buffer))
-         (mbuf-contents (minibuffer-completion-contents))
-         common-string-length)
-    ;; When reading a file name in the minibuffer,
-    ;; set default-directory in the minibuffer
-    ;; so it will get copied into the completion list buffer.
-    (if minibuffer-completing-file-name
-       (with-current-buffer mainbuf
-         (setq default-directory
-                (file-name-directory (expand-file-name mbuf-contents)))))
+         (base-dir
+          ;; When reading a file name in the minibuffer,
+          ;; try and find the right default-directory to set in the
+          ;; completion list buffer.
+          ;; FIXME: Why do we do that, actually?  --Stef
+          (if minibuffer-completing-file-name
+              (file-name-as-directory
+               (expand-file-name
+                (substring (minibuffer-completion-contents)
+                           0 (or completion-base-size 0)))))))
     (with-current-buffer standard-output
-      (let ((base-size completion-base-size)) ;Read before killing localvars.
+      (let ((base-size completion-base-size) ;Read before killing localvars.
+            (base-position completion-base-position))
         (completion-list-mode)
-        (set (make-local-variable 'completion-base-size) base-size))
+        (set (make-local-variable 'completion-base-size) base-size)
+        (set (make-local-variable 'completion-base-position) base-position))
       (set (make-local-variable 'completion-reference-buffer) mainbuf)
-      (unless completion-base-size
-        ;; This shouldn't be needed any more, but further analysis is needed
-        ;; to make sure it's the case.
-        (setq completion-base-size
-              (cond
-               (minibuffer-completing-file-name
-                ;; For file name completion, use the number of chars before
-                ;; the start of the file name component at point.
-                (with-current-buffer mainbuf
-                  (save-excursion
-                    (skip-chars-backward completion-root-regexp)
-                    (- (point) (minibuffer-prompt-end)))))
-               (minibuffer-completing-symbol nil)
-               ;; Otherwise, in minibuffer, the base size is 0.
-               ((minibufferp mainbuf) 0))))
+      (if base-dir (setq default-directory base-dir))
       ;; Maybe insert help string.
       (when completion-show-help
        (goto-char (point-min))
@@ -5826,10 +6029,10 @@ select the completion near point.\n\n"))))))
 (defun switch-to-completions ()
   "Select the completion list window."
   (interactive)
+  (let ((window (or (get-buffer-window "*Completions*" 0)
   ;; Make sure we have a completions window.
-  (or (get-buffer-window "*Completions*")
-      (minibuffer-completion-help))
-  (let ((window (get-buffer-window "*Completions*")))
+                    (progn (minibuffer-completion-help)
+                           (get-buffer-window "*Completions*" 0)))))
     (when window
       (select-window window)
       (goto-char (point-min))
@@ -5927,7 +6130,17 @@ PREFIX is the string that represents this modifier in an event type symbol."
    (kp-subtract ?-)
    (kp-decimal ?.)
    (kp-divide ?/)
-   (kp-equal ?=)))
+   (kp-equal ?=)
+   ;; Do the same for various keys that are represented as symbols under
+   ;; GUIs but naturally correspond to characters.
+   (backspace 127)
+   (delete 127)
+   (tab ?\t)
+   (linefeed ?\n)
+   (clear ?\C-l)
+   (return ?\C-m)
+   (escape ?\e)
+   ))
 \f
 ;;;;
 ;;;; forking a twin copy of a buffer.
@@ -6196,8 +6409,8 @@ have both Backspace, Delete and F1 keys.
 See also `normal-erase-is-backspace'."
   (interactive "P")
   (let ((enabled (or (and arg (> (prefix-numeric-value arg) 0))
-                    (and (not arg)
-                         (not (eq 1 (terminal-parameter
+                    (not (or arg
+                              (eq 1 (terminal-parameter
                                      nil 'normal-erase-is-backspace)))))))
     (set-terminal-parameter nil 'normal-erase-is-backspace
                            (if enabled 1 0))
@@ -6205,34 +6418,29 @@ See also `normal-erase-is-backspace'."
     (cond ((or (memq window-system '(x w32 ns pc))
               (memq system-type '(ms-dos windows-nt)))
           (let* ((bindings
-                  `(([C-delete] [C-backspace])
-                    ([M-delete] [M-backspace])
+                  `(([M-delete] [M-backspace])
                     ([C-M-delete] [C-M-backspace])
-                    (,esc-map
-                     [C-delete] [C-backspace])))
+                    ([?\e C-delete] [?\e C-backspace])))
                  (old-state (lookup-key local-function-key-map [delete])))
 
             (if enabled
                 (progn
                   (define-key local-function-key-map [delete] [?\C-d])
                   (define-key local-function-key-map [kp-delete] [?\C-d])
-                  (define-key local-function-key-map [backspace] [?\C-?]))
+                  (define-key local-function-key-map [backspace] [?\C-?])
+                   (dolist (b bindings)
+                     ;; Not sure if input-decode-map is really right, but
+                     ;; keyboard-translate-table (used below) only works
+                     ;; for integer events, and key-translation-table is
+                     ;; global (like the global-map, used earlier).
+                     (define-key input-decode-map (car b) nil)
+                     (define-key input-decode-map (cadr b) nil)))
               (define-key local-function-key-map [delete] [?\C-?])
               (define-key local-function-key-map [kp-delete] [?\C-?])
-              (define-key local-function-key-map [backspace] [?\C-?]))
-
-            ;; Maybe swap bindings of C-delete and C-backspace, etc.
-            (unless (equal old-state (lookup-key local-function-key-map [delete]))
-              (dolist (binding bindings)
-                (let ((map global-map))
-                  (when (keymapp (car binding))
-                    (setq map (car binding) binding (cdr binding)))
-                  (let* ((key1 (nth 0 binding))
-                         (key2 (nth 1 binding))
-                         (binding1 (lookup-key map key1))
-                         (binding2 (lookup-key map key2)))
-                    (define-key map key1 binding2)
-                    (define-key map key2 binding1)))))))
+              (define-key local-function-key-map [backspace] [?\C-?])
+               (dolist (b bindings)
+                 (define-key input-decode-map (car b) (cadr b))
+                 (define-key input-decode-map (cadr b) (car b))))))
          (t
           (if enabled
               (progn
@@ -6242,7 +6450,7 @@ See also `normal-erase-is-backspace'."
             (keyboard-translate ?\C-? ?\C-?))))
 
     (run-hooks 'normal-erase-is-backspace-hook)
-    (if (interactive-p)
+    (if (called-interactively-p 'interactive)
        (message "Delete key deletes %s"
                 (if (terminal-parameter nil 'normal-erase-is-backspace)
                     "forward" "backward")))))