(vc-register): Allow registering a file passed as a
[bpt/emacs.git] / lisp / simple.el
index daedae6..572d7d6 100644 (file)
@@ -1,7 +1,8 @@
 ;;; 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 Free Software Foundation, Inc.
+;;   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+;;   Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 ;; Keywords: internal
@@ -10,7 +11,7 @@
 
 ;; GNU Emacs 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)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
@@ -85,34 +86,22 @@ 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."
   (setq frame (or frame (selected-frame)))
-  (or (get-next-valid-buffer (frame-parameter frame 'buried-buffer-list)
-                            buffer visible-ok frame)
-      (get-next-valid-buffer (nreverse (buffer-list frame))
-                            buffer visible-ok 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*"))))
-
 (defun next-buffer ()
   "Switch to the next buffer in cyclic order."
   (interactive)
-  (let ((buffer (current-buffer))
-       (bbl (frame-parameter nil 'buried-buffer-list)))
+  (let ((buffer (current-buffer)))
     (switch-to-buffer (other-buffer buffer t))
-    (bury-buffer buffer)
-    (set-frame-parameter nil 'buried-buffer-list
-                        (cons buffer (delq buffer bbl)))))
+    (bury-buffer buffer)))
 
 (defun previous-buffer ()
   "Switch to the previous buffer in cyclic order."
   (interactive)
-  (let ((buffer (last-buffer (current-buffer) t))
-       (bbl (frame-parameter nil 'buried-buffer-list)))
-    (switch-to-buffer buffer)
-    ;; Clean up buried-buffer-list up to and including the chosen buffer.
-    (while (and bbl (not (eq (car bbl) buffer)))
-      (setq bbl (cdr bbl)))
-    (set-frame-parameter nil 'buried-buffer-list bbl)))
+  (switch-to-buffer (last-buffer (current-buffer) t)))
 
 \f
 ;;; next-error support framework
@@ -156,6 +145,15 @@ If `fringe-arrow', indicate the locus by the fringe arrow."
   :group 'next-error
   :version "22.1")
 
+(defcustom next-error-recenter nil
+  "*Display the line in the visited source file recentered as specified.
+If non-nil, the value is passed directly to `recenter'."
+  :type '(choice (integer :tag "Line to recenter to")
+                 (const :tag "Center of window" (4))
+                 (const :tag "No recentering" nil))
+  :group 'next-error
+  :version "23.1")
+
 (defcustom next-error-hook nil
   "*List of hook functions run by `next-error' after visiting source file."
   :type 'hook
@@ -305,6 +303,8 @@ See variables `compilation-parse-errors-function' and
     ;; we know here that next-error-function is a valid symbol we can funcall
     (with-current-buffer next-error-last-buffer
       (funcall next-error-function (prefix-numeric-value arg) reset)
+      (when next-error-recenter
+        (recenter next-error-recenter))
       (run-hooks 'next-error-hook))))
 
 (defun next-error-internal ()
@@ -313,6 +313,8 @@ See variables `compilation-parse-errors-function' and
   ;; we know here that next-error-function is a valid symbol we can funcall
   (with-current-buffer next-error-last-buffer
     (funcall next-error-function 0 nil)
+    (when next-error-recenter
+      (recenter next-error-recenter))
     (run-hooks 'next-error-hook)))
 
 (defalias 'goto-next-locus 'next-error)
@@ -456,7 +458,7 @@ than the value of `fill-column' and ARG is nil."
     ;; Mark the newline(s) `hard'.
     (if use-hard-newlines
        (set-hard-newline-properties
-        (- (point) (if arg (prefix-numeric-value arg) 1)) (point)))
+        (- (point) (prefix-numeric-value arg)) (point)))
     ;; If the newline leaves the previous line blank,
     ;; and we have a left margin, delete that from the blank line.
     (or flag
@@ -631,7 +633,16 @@ column specified by the function `current-left-margin'."
     (newline)
     (save-excursion
       (goto-char pos)
+      ;; We are at EOL before the call to indent-according-to-mode, and
+      ;; after it we usually are as well, but not always.  We tried to
+      ;; address it with `save-excursion' but that uses a normal marker
+      ;; whereas we need `move after insertion', so we do the save/restore
+      ;; by hand.
+      (setq pos (copy-marker pos t))
       (indent-according-to-mode)
+      (goto-char pos)
+      ;; Remove the trailing white-space after indentation because
+      ;; indentation may introduce the whitespace.
       (delete-horizontal-space t))
     (indent-according-to-mode)))
 
@@ -1042,7 +1053,7 @@ display the result of expression evaluation."
                (if (boundp 'edebug-active) edebug-active)))
       (let ((char-string
              (if (or (if (boundp 'edebug-active) edebug-active)
-                     (memq this-command '(eval-last-sexp eval-print-last-sexp)))
+                    (memq this-command '(eval-last-sexp eval-print-last-sexp)))
                  (prin1-char value))))
         (if char-string
             (format " (#o%o, #x%x, %s)" value value char-string)
@@ -1287,55 +1298,67 @@ makes the search case-sensitive."
 
 (defvar minibuffer-temporary-goal-position nil)
 
+(defun goto-history-element (nabs)
+  "Puts element of the minibuffer history in the minibuffer.
+The argument NABS specifies the absolute history position."
+  (interactive "p")
+  (let ((minimum (if minibuffer-default
+                    (- (if (listp minibuffer-default)
+                           (length minibuffer-default)
+                         1))
+                  0))
+       elt minibuffer-returned-to-present)
+    (if (and (zerop minibuffer-history-position)
+            (null minibuffer-text-before-history))
+       (setq minibuffer-text-before-history
+             (minibuffer-contents-no-properties)))
+    (if (< nabs minimum)
+       (if minibuffer-default
+           (error "End of history; no next item")
+         (error "End of history; no default available")))
+    (if (> nabs (length (symbol-value minibuffer-history-variable)))
+       (error "Beginning of history; no preceding item"))
+    (unless (memq last-command '(next-history-element
+                                previous-history-element))
+      (let ((prompt-end (minibuffer-prompt-end)))
+       (set (make-local-variable 'minibuffer-temporary-goal-position)
+            (cond ((<= (point) prompt-end) prompt-end)
+                  ((eobp) nil)
+                  (t (point))))))
+    (goto-char (point-max))
+    (delete-minibuffer-contents)
+    (setq minibuffer-history-position nabs)
+    (cond ((< nabs 0)
+          (setq elt (if (listp minibuffer-default)
+                        (nth (1- (abs nabs)) minibuffer-default)
+                      minibuffer-default)))
+         ((= nabs 0)
+          (setq elt (or minibuffer-text-before-history ""))
+          (setq minibuffer-returned-to-present t)
+          (setq minibuffer-text-before-history nil))
+         (t (setq elt (nth (1- minibuffer-history-position)
+                           (symbol-value minibuffer-history-variable)))))
+    (insert
+     (if (and (eq minibuffer-history-sexp-flag (minibuffer-depth))
+             (not minibuffer-returned-to-present))
+        (let ((print-level nil))
+          (prin1-to-string elt))
+       elt))
+    (goto-char (or minibuffer-temporary-goal-position (point-max)))))
+
 (defun next-history-element (n)
   "Puts next element of the minibuffer history in the minibuffer.
 With argument N, it uses the Nth following element."
   (interactive "p")
   (or (zerop n)
-      (let ((narg (- minibuffer-history-position n))
-           (minimum (if minibuffer-default -1 0))
-           elt minibuffer-returned-to-present)
-       (if (and (zerop minibuffer-history-position)
-                (null minibuffer-text-before-history))
-           (setq minibuffer-text-before-history
-                 (minibuffer-contents-no-properties)))
-       (if (< narg minimum)
-           (if minibuffer-default
-               (error "End of history; no next item")
-             (error "End of history; no default available")))
-       (if (> narg (length (symbol-value minibuffer-history-variable)))
-           (error "Beginning of history; no preceding item"))
-       (unless (memq last-command '(next-history-element
-                                    previous-history-element))
-         (let ((prompt-end (minibuffer-prompt-end)))
-           (set (make-local-variable 'minibuffer-temporary-goal-position)
-                (cond ((<= (point) prompt-end) prompt-end)
-                      ((eobp) nil)
-                      (t (point))))))
-       (goto-char (point-max))
-       (delete-minibuffer-contents)
-       (setq minibuffer-history-position narg)
-       (cond ((= narg -1)
-              (setq elt minibuffer-default))
-             ((= narg 0)
-              (setq elt (or minibuffer-text-before-history ""))
-              (setq minibuffer-returned-to-present t)
-              (setq minibuffer-text-before-history nil))
-             (t (setq elt (nth (1- minibuffer-history-position)
-                               (symbol-value minibuffer-history-variable)))))
-       (insert
-        (if (and (eq minibuffer-history-sexp-flag (minibuffer-depth))
-                 (not minibuffer-returned-to-present))
-            (let ((print-level nil))
-              (prin1-to-string elt))
-          elt))
-       (goto-char (or minibuffer-temporary-goal-position (point-max))))))
+      (goto-history-element (- minibuffer-history-position n))))
 
 (defun previous-history-element (n)
   "Puts previous element of the minibuffer history in the minibuffer.
 With argument N, it uses the Nth previous element."
   (interactive "p")
-  (next-history-element (- n)))
+  (or (zerop n)
+      (goto-history-element (+ minibuffer-history-position n))))
 
 (defun next-complete-history-element (n)
   "Get next history element which completes the minibuffer before the point.
@@ -1368,6 +1391,137 @@ Return 0 if current buffer is not a minibuffer."
   ;; the buffer; this should be 0 for normal buffers.
   (1- (minibuffer-prompt-end)))
 \f
+;; isearch minibuffer history
+(add-hook 'minibuffer-setup-hook 'minibuffer-history-isearch-setup)
+
+(defvar minibuffer-history-isearch-message-overlay)
+(make-variable-buffer-local 'minibuffer-history-isearch-message-overlay)
+
+(defun minibuffer-history-isearch-setup ()
+  "Set up a minibuffer for using isearch to search the minibuffer history.
+Intended to be added to `minibuffer-setup-hook'."
+  (set (make-local-variable 'isearch-search-fun-function)
+       'minibuffer-history-isearch-search)
+  (set (make-local-variable 'isearch-message-function)
+       'minibuffer-history-isearch-message)
+  (set (make-local-variable 'isearch-wrap-function)
+       'minibuffer-history-isearch-wrap)
+  (set (make-local-variable 'isearch-push-state-function)
+       'minibuffer-history-isearch-push-state)
+  (add-hook 'isearch-mode-end-hook 'minibuffer-history-isearch-end nil t))
+
+(defun minibuffer-history-isearch-end ()
+  "Clean up the minibuffer after terminating isearch in the minibuffer."
+  (if minibuffer-history-isearch-message-overlay
+      (delete-overlay minibuffer-history-isearch-message-overlay)))
+
+(defun minibuffer-history-isearch-search ()
+  "Return the proper search function, for isearch in minibuffer history."
+  (cond
+   (isearch-word
+    (if isearch-forward 'word-search-forward 'word-search-backward))
+   (t
+    (lambda (string bound noerror)
+      (let ((search-fun
+            ;; Use standard functions to search within minibuffer text
+             (cond
+              (isearch-regexp
+               (if isearch-forward 're-search-forward 're-search-backward))
+              (t
+               (if isearch-forward 'search-forward 'search-backward))))
+           found)
+       ;; Avoid lazy-highlighting matches in the minibuffer prompt when
+       ;; searching forward.  Lazy-highlight calls this lambda with the
+       ;; bound arg, so skip the minibuffer prompt.
+       (if (and bound isearch-forward (< (point) (minibuffer-prompt-end)))
+           (goto-char (minibuffer-prompt-end)))
+        (or
+        ;; 1. First try searching in the initial minibuffer text
+        (funcall search-fun string
+                 (if isearch-forward bound (minibuffer-prompt-end))
+                 noerror)
+        ;; 2. If the above search fails, start putting next/prev history
+        ;; elements in the minibuffer successively, and search the string
+        ;; in them.  Do this only when bound is nil (i.e. not while
+        ;; lazy-highlighting search strings in the current minibuffer text).
+        (unless bound
+          (condition-case nil
+              (progn
+                (while (not found)
+                  (cond (isearch-forward
+                         (next-history-element 1)
+                         (goto-char (minibuffer-prompt-end)))
+                        (t
+                         (previous-history-element 1)
+                         (goto-char (point-max))))
+                  (setq isearch-barrier (point) isearch-opoint (point))
+                  ;; After putting the next/prev history element, search
+                  ;; the string in them again, until next-history-element
+                  ;; or previous-history-element raises an error at the
+                  ;; beginning/end of history.
+                  (setq found (funcall search-fun string
+                                       (unless isearch-forward
+                                         ;; For backward search, don't search
+                                         ;; in the minibuffer prompt
+                                         (minibuffer-prompt-end))
+                                       noerror)))
+                ;; Return point of the new search result
+                (point))
+            ;; Return nil when next(prev)-history-element fails
+            (error nil)))))))))
+
+(defun minibuffer-history-isearch-message (&optional c-q-hack ellipsis)
+  "Display the minibuffer history search prompt.
+If there are no search errors, this function displays an overlay with
+the isearch prompt which replaces the original minibuffer prompt.
+Otherwise, it displays the standard isearch message returned from
+`isearch-message'."
+  (if (not (and (minibufferp) isearch-success (not isearch-error)))
+      ;; Use standard function `isearch-message' when not in the minibuffer,
+      ;; or search fails, or has an error (like incomplete regexp).
+      ;; This function overwrites minibuffer text with isearch message,
+      ;; so it's possible to see what is wrong in the search string.
+      (isearch-message c-q-hack ellipsis)
+    ;; Otherwise, put the overlay with the standard isearch prompt over
+    ;; the initial minibuffer prompt.
+    (if (overlayp minibuffer-history-isearch-message-overlay)
+       (move-overlay minibuffer-history-isearch-message-overlay
+                     (point-min) (minibuffer-prompt-end))
+      (setq minibuffer-history-isearch-message-overlay
+           (make-overlay (point-min) (minibuffer-prompt-end)))
+      (overlay-put minibuffer-history-isearch-message-overlay 'evaporate t))
+    (overlay-put minibuffer-history-isearch-message-overlay
+                'display (isearch-message-prefix c-q-hack ellipsis))
+    ;; And clear any previous isearch message.
+    (message "")))
+
+(defun minibuffer-history-isearch-wrap ()
+  "Wrap the minibuffer history search when search is failed.
+Move point to the first history element for a forward search,
+or to the last history element for a backward search."
+  (unless isearch-word
+    ;; When `minibuffer-history-isearch-search' fails on reaching the
+    ;; beginning/end of the history, wrap the search to the first/last
+    ;; minibuffer history element.
+    (if isearch-forward
+       (goto-history-element (length (symbol-value minibuffer-history-variable)))
+      (goto-history-element 0))
+    (setq isearch-success t))
+  (goto-char (if isearch-forward (minibuffer-prompt-end) (point-max))))
+
+(defun minibuffer-history-isearch-push-state ()
+  "Save a function restoring the state of minibuffer history search.
+Save `minibuffer-history-position' to the additional state parameter
+in the search status stack."
+  `(lambda (cmd)
+     (minibuffer-history-isearch-pop-state cmd ,minibuffer-history-position)))
+
+(defun minibuffer-history-isearch-pop-state (cmd hist-pos)
+  "Restore the minibuffer history search state.
+Go to the history element by the absolute history position `hist-pos'."
+  (goto-history-element hist-pos))
+
+\f
 ;Put this on C-x u, so we can force that rather than C-_ into startup msg
 (defalias 'advertised-undo 'undo)
 
@@ -2189,6 +2343,18 @@ value passed."
       (when stderr-file (delete-file stderr-file))
       (when lc (delete-file lc)))))
 
+(defun start-file-process (name buffer program &rest program-args)
+  "Start a program in a subprocess.  Return the process object for it.
+Similar to `start-process', but may invoke a file handler based on
+`default-directory'.  The current working directory of the
+subprocess is `default-directory'.
+
+PROGRAM and PROGRAM-ARGS might be file names.  They are not
+objects of file handler invocation."
+  (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))))
+
 
 \f
 (defvar universal-argument-map
@@ -2409,6 +2575,11 @@ of the Emacs kill ring should be used.  If the function returns a
 string, then the caller of the function \(usually `current-kill')
 should put this string in the kill ring as the latest kill.
 
+This function may also return a list of strings if the window
+system supports multiple selections. The first string will be
+used as the pasted text, but the other will be placed in the
+kill ring for easy access via `yank-pop'.
+
 Note that the function should return a string only if a program other
 than Emacs has provided a string for pasting; if Emacs provided the
 most recent string, the function should return nil.  If it is
@@ -2490,11 +2661,11 @@ If `interprogram-cut-function' is set, pass the resulting kill to it."
 
 (defun current-kill (n &optional do-not-move)
   "Rotate the yanking point by N places, and then return that kill.
-If N is zero, `interprogram-paste-function' is set, and calling it
-returns a string, then that string is added to the front of the
-kill ring and returned as the latest kill.
-If optional arg DO-NOT-MOVE is non-nil, then don't actually move the
-yanking point; just return the Nth kill forward."
+If N is zero, `interprogram-paste-function' is set, and calling it returns a
+string or list of strings, then that string (or list) is added to the front
+of the kill ring and the string (or first string in the list) is returned as
+the latest kill.  If optional arg DO-NOT-MOVE is non-nil, then don't
+actually move the yanking point; just return the Nth kill forward."
   (let ((interprogram-paste (and (= n 0)
                                 interprogram-paste-function
                                 (funcall interprogram-paste-function))))
@@ -2504,8 +2675,10 @@ yanking point; just return the Nth kill forward."
          ;; text to the kill ring, so Emacs doesn't try to own the
          ;; selection, with identical text.
          (let ((interprogram-cut-function nil))
-           (kill-new interprogram-paste))
-         interprogram-paste)
+           (if (listp interprogram-paste)
+             (mapc 'kill-new (nreverse interprogram-paste))
+             (kill-new interprogram-paste)))
+         (car kill-ring))
       (or kill-ring (error "Kill ring is empty"))
       (let ((ARGth-kill-element
             (nthcdr (mod (- n (length kill-ring-yank-pointer))
@@ -2591,7 +2764,9 @@ text.  See `insert-for-yank'."
   "Save the region as if killed, but don't kill it.
 In Transient Mark mode, deactivate the mark.
 If `interprogram-cut-function' is non-nil, also save the text for a window
-system cut and paste."
+system cut and paste.
+
+This command's old key binding has been given to `kill-ring-save'."
   (interactive "r")
   (if (eq last-command 'kill-region)
       (kill-append (filter-buffer-substring beg end) (< end beg))
@@ -2661,7 +2836,7 @@ The argument is used for internal purposes; do not supply one."
 (defcustom yank-excluded-properties
   '(read-only invisible intangible field mouse-face help-echo local-map keymap
     yank-handler follow-link fontified)
-  "*Text properties to discard when yanking.
+  "Text properties to discard when yanking.
 The value should be a list of text properties to discard or t,
 which means to discard all text properties."
   :type '(choice (const :tag "All" t) (repeat symbol))
@@ -3469,7 +3644,7 @@ The beginning of a blank line does not count as the end of a line."
   "Current goal column for vertical motion.
 It is the column where point was
 at the start of current run of vertical motion commands.
-When the `track-eol' feature is doing its job, the value is 9999.")
+When the `track-eol' feature is doing its job, the value is `most-positive-fixnum'.")
 
 (defcustom line-move-ignore-invisible t
   "*Non-nil means \\[next-line] and \\[previous-line] ignore invisible lines.
@@ -3477,15 +3652,6 @@ Outline mode sets this."
   :type 'boolean
   :group 'editing-basics)
 
-(defun line-move-invisible-p (pos)
-  "Return non-nil if the character after POS is currently invisible."
-  (let ((prop
-        (get-char-property pos 'invisible)))
-    (if (eq buffer-invisibility-spec t)
-       prop
-      (or (memq prop buffer-invisibility-spec)
-         (assq prop buffer-invisibility-spec)))))
-
 ;; Returns non-nil if partial move was done.
 (defun line-move-partial (arg noerror to-end)
   (if (< arg 0)
@@ -3500,7 +3666,7 @@ Outline mode sets this."
           (vpos (nth 1 lh))
           (ypos (nth 2 lh))
           (rbot (nth 3 lh))
-          ppos py vs)
+          py vs)
       (when (or (null lh)
                (>= rbot (frame-char-height))
                (<= ypos (- (frame-char-height))))
@@ -3577,11 +3743,11 @@ Outline mode sets this."
                             ;; Don't count beg of empty line as end of line
                             ;; unless we just did explicit end-of-line.
                             (or (not (bolp)) (eq last-command 'move-end-of-line)))
-                       9999
+                       most-positive-fixnum
                      (current-column))))
 
-         (if (and (not (integerp selective-display))
-                  (not line-move-ignore-invisible))
+         (if (not (or (integerp selective-display)
+                       line-move-ignore-invisible))
              ;; Use just newline characters.
              ;; Set ARG to 0 if we move as many lines as requested.
              (or (if (> arg 0)
@@ -3605,7 +3771,7 @@ Outline mode sets this."
              (while (and (> arg 0) (not done))
                ;; If the following character is currently invisible,
                ;; skip all characters with that same `invisible' property value.
-               (while (and (not (eobp)) (line-move-invisible-p (point)))
+               (while (and (not (eobp)) (invisible-p (point)))
                  (goto-char (next-char-property-change (point))))
                ;; Move a line.
                ;; We don't use `end-of-line', since we want to escape
@@ -3623,7 +3789,7 @@ Outline mode sets this."
                    (setq done t)))
                 ((and (> arg 1)  ;; Use vertical-motion for last move
                       (not (integerp selective-display))
-                      (not (line-move-invisible-p (point))))
+                      (not (invisible-p (point))))
                  ;; We avoid vertical-motion when possible
                  ;; because that has to fontify.
                  (forward-line 1))
@@ -3652,7 +3818,7 @@ Outline mode sets this."
                    (setq done t)))
                 ((and (< arg -1) ;; Use vertical-motion for last move
                       (not (integerp selective-display))
-                      (not (line-move-invisible-p (1- (point)))))
+                      (not (invisible-p (1- (point)))))
                  (forward-line -1))
                 ((zerop (vertical-motion -1))
                  (if (not noerror)
@@ -3664,7 +3830,7 @@ Outline mode sets this."
                          ;; if our target is the middle of this line.
                          (or (zerop (or goal-column temporary-goal-column))
                              (< arg 0))
-                         (not (bobp)) (line-move-invisible-p (1- (point))))
+                         (not (bobp)) (invisible-p (1- (point))))
                    (goto-char (previous-char-property-change (point))))))))
          ;; This is the value the function returns.
          (= arg 0))
@@ -3696,7 +3862,7 @@ Outline mode sets this."
             (save-excursion
               ;; Like end-of-line but ignores fields.
               (skip-chars-forward "^\n")
-              (while (and (not (eobp)) (line-move-invisible-p (point)))
+              (while (and (not (eobp)) (invisible-p (point)))
                 (goto-char (next-char-property-change (point)))
                 (skip-chars-forward "^\n"))
               (point))))
@@ -3779,13 +3945,13 @@ and `current-column' to be able to ignore invisible text."
     (move-to-column col))
 
   (when (and line-move-ignore-invisible
-            (not (bolp)) (line-move-invisible-p (1- (point))))
+            (not (bolp)) (invisible-p (1- (point))))
     (let ((normal-location (point))
          (normal-column (current-column)))
       ;; If the following character is currently invisible,
       ;; skip all characters with that same `invisible' property value.
       (while (and (not (eobp))
-                 (line-move-invisible-p (point)))
+                 (invisible-p (point)))
        (goto-char (next-char-property-change (point))))
       ;; Have we advanced to a larger column position?
       (if (> (current-column) normal-column)
@@ -3798,7 +3964,7 @@ and `current-column' to be able to ignore invisible text."
        ;; but with a more reasonable buffer position.
        (goto-char normal-location)
        (let ((line-beg (save-excursion (beginning-of-line) (point))))
-         (while (and (not (bolp)) (line-move-invisible-p (1- (point))))
+         (while (and (not (bolp)) (invisible-p (1- (point))))
            (goto-char (previous-char-property-change (point) line-beg))))))))
 
 (defun move-end-of-line (arg)
@@ -3819,8 +3985,9 @@ To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
                 (and (line-move arg t)
                      (not (bobp))
                      (progn
-                       (while (and (not (bobp)) (line-move-invisible-p (1- (point))))
-                         (goto-char (previous-char-property-change (point))))
+                       (while (and (not (bobp)) (invisible-p (1- (point))))
+                         (goto-char (previous-single-char-property-change
+                                      (point) 'invisible)))
                        (backward-char 1)))
                 (point)))))
        (goto-char newpos)
@@ -3847,7 +4014,7 @@ To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
   (or arg (setq arg 1))
 
   (let ((orig (point))
-       start first-vis first-vis-field-value)
+       first-vis first-vis-field-value)
 
     ;; Move by lines, if ARG is not 1 (the default).
     (if (/= arg 1)
@@ -3855,13 +4022,12 @@ To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
 
     ;; Move to beginning-of-line, ignoring fields and invisibles.
     (skip-chars-backward "^\n")
-    (while (and (not (bobp)) (line-move-invisible-p (1- (point))))
+    (while (and (not (bobp)) (invisible-p (1- (point))))
       (goto-char (previous-char-property-change (point)))
       (skip-chars-backward "^\n"))
-    (setq start (point))
 
     ;; Now find first visible char in the line
-    (while (and (not (eobp)) (line-move-invisible-p (point)))
+    (while (and (not (eobp)) (invisible-p (point)))
       (goto-char (next-char-property-change (point))))
     (setq first-vis (point))
 
@@ -4167,13 +4333,6 @@ If optional arg REALLY-WORD is non-nil, it finds just a word."
                 regexp)
   :group 'fill)
 
-(defvar comment-line-break-function 'comment-indent-new-line
-  "*Mode-specific function which line breaks and continues a comment.
-
-This function is only called during auto-filling of a comment section.
-The function should take a single optional argument, which is a flag
-indicating whether it should use soft newlines.")
-
 ;; This function is used as the auto-fill-function of a buffer
 ;; when Auto-Fill mode is enabled.
 ;; It returns t if it really did any work.
@@ -4247,10 +4406,10 @@ indicating whether it should use soft newlines.")
              (if (save-excursion
                    (skip-chars-backward " \t")
                    (= (point) fill-point))
-                 (funcall comment-line-break-function t)
+                 (default-indent-new-line t)
                (save-excursion
                  (goto-char fill-point)
-                 (funcall comment-line-break-function t)))
+                 (default-indent-new-line t)))
              ;; Now do justification, if required
              (if (not (eq justify 'left))
                  (save-excursion
@@ -4265,6 +4424,43 @@ indicating whether it should use soft newlines.")
       (justify-current-line justify t t)
       t)))
 
+(defvar comment-line-break-function 'comment-indent-new-line
+  "*Mode-specific function which line breaks and continues a comment.
+This function is called during auto-filling when a comment syntax
+is defined.
+The function should take a single optional argument, which is a flag
+indicating whether it should use soft newlines.")
+
+(defun default-indent-new-line (&optional soft)
+  "Break line at point and indent.
+If a comment syntax is defined, call `comment-indent-new-line'.
+
+The inserted newline is marked hard if variable `use-hard-newlines' is true,
+unless optional argument SOFT is non-nil."
+  (interactive)
+  (if comment-start
+      (funcall comment-line-break-function soft)
+    ;; Insert the newline before removing empty space so that markers
+    ;; get preserved better.
+    (if soft (insert-and-inherit ?\n) (newline 1))
+    (save-excursion (forward-char -1) (delete-horizontal-space))
+    (delete-horizontal-space)
+
+    (if (and fill-prefix (not adaptive-fill-mode))
+       ;; Blindly trust a non-adaptive fill-prefix.
+       (progn
+         (indent-to-left-margin)
+         (insert-before-markers-and-inherit fill-prefix))
+
+      (cond
+       ;; If there's an adaptive prefix, use it unless we're inside
+       ;; a comment and the prefix is not a comment starter.
+       (fill-prefix
+       (indent-to-left-margin)
+       (insert-and-inherit fill-prefix))
+       ;; If we're not inside a comment, just try to indent.
+       (t (indent-according-to-mode))))))
+
 (defvar normal-auto-fill-function 'do-auto-fill
   "The function to use for `auto-fill-function' if Auto Fill mode is turned on.
 Some major modes set this.")
@@ -4343,8 +4539,9 @@ The variable `selective-display' has a separate value for each buffer."
 
 (defun toggle-truncate-lines (&optional arg)
   "Toggle whether to fold or truncate long lines for the current buffer.
-With arg, truncate long lines iff arg is positive.
-Note that in side-by-side windows, truncation is always enabled."
+With prefix argument ARG, truncate long lines if ARG is positive,
+otherwise don't truncate them.  Note that in side-by-side
+windows, truncation is always enabled."
   (interactive "P")
   (setq truncate-lines
        (if (null arg)
@@ -4367,11 +4564,11 @@ Note that in side-by-side windows, truncation is always enabled."
 
 (defun overwrite-mode (arg)
   "Toggle overwrite mode.
-With arg, turn overwrite mode on iff arg is positive.
-In overwrite mode, printing characters typed in replace existing text
-on a one-for-one basis, rather than pushing it to the right.  At the
-end of a line, such characters extend the line.  Before a tab,
-such characters insert until the tab is filled in.
+With prefix argument ARG, turn overwrite mode on if ARG is positive,
+otherwise turn it off.  In overwrite mode, printing characters typed
+in replace existing text on a one-for-one basis, rather than pushing
+it to the right.  At the end of a line, such characters extend the line.
+Before a tab, such characters insert until the tab is filled in.
 \\[quoted-insert] still inserts characters in overwrite mode; this
 is supposed to make it easier to insert characters when necessary."
   (interactive "P")
@@ -4383,14 +4580,13 @@ is supposed to make it easier to insert characters when necessary."
 
 (defun binary-overwrite-mode (arg)
   "Toggle binary overwrite mode.
-With arg, turn binary overwrite mode on iff arg is positive.
-In binary overwrite mode, printing characters typed in replace
-existing text.  Newlines are not treated specially, so typing at the
-end of a line joins the line to the next, with the typed character
-between them.  Typing before a tab character simply replaces the tab
-with the character typed.
-\\[quoted-insert] replaces the text at the cursor, just as ordinary
-typing characters do.
+With prefix argument ARG, turn binary overwrite mode on if ARG is
+positive, otherwise turn it off.  In binary overwrite mode, printing
+characters typed in replace existing text.  Newlines are not treated
+specially, so typing at the end of a line joins the line to the next,
+with the typed character between them.  Typing before a tab character
+simply replaces the tab with the character typed.  \\[quoted-insert]
+replaces the text at the cursor, just as ordinary typing characters do.
 
 Note that binary overwrite mode is not its own minor mode; it is a
 specialization of overwrite mode, entered by setting the
@@ -4405,9 +4601,9 @@ specialization of overwrite mode, entered by setting the
 
 (define-minor-mode line-number-mode
   "Toggle Line Number mode.
-With arg, turn Line Number mode on iff arg is positive.
-When Line Number mode is enabled, the line number appears
-in the mode line.
+With arg, turn Line Number mode on if arg is positive, otherwise
+turn it off.  When Line Number mode is enabled, the line number
+appears in the mode line.
 
 Line numbers do not appear for very large buffers and buffers
 with very long lines; see variables `line-number-display-limit'
@@ -4416,16 +4612,16 @@ and `line-number-display-limit-width'."
 
 (define-minor-mode column-number-mode
   "Toggle Column Number mode.
-With arg, turn Column Number mode on iff arg is positive.
-When Column Number mode is enabled, the column number appears
-in the mode line."
+With arg, turn Column Number mode on if arg is positive,
+otherwise turn it off.  When Column Number mode is enabled, the
+column number appears in the mode line."
   :global t :group 'mode-line)
 
 (define-minor-mode size-indication-mode
   "Toggle Size Indication mode.
-With arg, turn Size Indication mode on iff arg is positive.  When
-Size Indication mode is enabled, the size of the accessible part
-of the buffer appears in the mode line."
+With arg, turn Size Indication mode on if arg is positive,
+otherwise turn it off.  When Size Indication mode is enabled, the
+size of the accessible part of the buffer appears in the mode line."
   :global t :group 'mode-line)
 \f
 (defgroup paren-blinking nil
@@ -4479,86 +4675,92 @@ it skips the contents of comments that end before point."
                                 (skip-syntax-backward "/\\")
                                 (point))))))
     (let* ((oldpos (point))
-          blinkpos
-          message-log-max  ; Don't log messages about paren matching.
-          matching-paren
-          open-paren-line-string)
-      (save-excursion
-       (save-restriction
-         (if blink-matching-paren-distance
-             (narrow-to-region (max (minibuffer-prompt-end)
-                                    (- (point) blink-matching-paren-distance))
-                               oldpos))
-         (condition-case ()
-             (let ((parse-sexp-ignore-comments
-                    (and parse-sexp-ignore-comments
-                         (not blink-matching-paren-dont-ignore-comments))))
-               (setq blinkpos (scan-sexps oldpos -1)))
-           (error nil)))
-       (and blinkpos
-            ;; Not syntax '$'.
-            (not (eq (syntax-class (syntax-after blinkpos)) 8))
-            (setq matching-paren
-                  (let ((syntax (syntax-after blinkpos)))
-                    (and (consp syntax)
-                         (eq (syntax-class syntax) 4)
-                         (cdr syntax)))))
-       (cond
-        ((not (or (eq matching-paren (char-before oldpos))
-                   ;; The cdr might hold a new paren-class info rather than
-                   ;; a matching-char info, in which case the two CDRs
-                   ;; should match.
-                   (eq matching-paren (cdr (syntax-after (1- oldpos))))))
-         (message "Mismatched parentheses"))
-        ((not blinkpos)
-         (if (not blink-matching-paren-distance)
-             (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.
-         (and blink-matching-paren-on-screen
-              (not show-paren-mode)
-              (save-excursion
-                (goto-char blinkpos)
-                (sit-for blink-matching-delay))))
-        (t
-         (save-excursion
-           (goto-char blinkpos)
-           (setq open-paren-line-string
-                 ;; Show what precedes the open in its line, if anything.
-                 (if (save-excursion
-                       (skip-chars-backward " \t")
-                       (not (bolp)))
-                     (buffer-substring (line-beginning-position)
-                                       (1+ blinkpos))
-                   ;; Show what follows the open in its line, if anything.
-                   (if (save-excursion
-                         (forward-char 1)
-                         (skip-chars-forward " \t")
-                         (not (eolp)))
-                       (buffer-substring blinkpos
-                                         (line-end-position))
-                     ;; Otherwise show the previous nonblank line,
-                     ;; if there is one.
-                     (if (save-excursion
-                           (skip-chars-backward "\n \t")
-                           (not (bobp)))
-                         (concat
-                          (buffer-substring (progn
-                                              (skip-chars-backward "\n \t")
-                                              (line-beginning-position))
-                                            (progn (end-of-line)
-                                                   (skip-chars-backward " \t")
-                                                   (point)))
-                          ;; Replace the newline and other whitespace with `...'.
-                          "..."
-                          (buffer-substring blinkpos (1+ blinkpos)))
-                       ;; There is nothing to show except the char itself.
-                       (buffer-substring blinkpos (1+ blinkpos)))))))
-         (message "Matches %s"
-                  (substring-no-properties open-paren-line-string))))))))
-
-;Turned off because it makes dbx bomb out.
+          (message-log-max nil)  ; Don't log messages about paren matching.
+          (atdollar (eq (syntax-class (syntax-after (1- oldpos))) 8))
+          (isdollar)
+          (blinkpos
+            (save-excursion
+              (save-restriction
+                (if blink-matching-paren-distance
+                    (narrow-to-region
+                     (max (minibuffer-prompt-end) ;(point-min) unless minibuf.
+                          (- (point) blink-matching-paren-distance))
+                     oldpos))
+                (let ((parse-sexp-ignore-comments
+                       (and parse-sexp-ignore-comments
+                            (not blink-matching-paren-dont-ignore-comments))))
+                  (condition-case ()
+                      (scan-sexps oldpos -1)
+                    (error nil))))))
+          (matching-paren
+            (and blinkpos
+                 ;; Not syntax '$'.
+                 (not (setq isdollar
+                            (eq (syntax-class (syntax-after blinkpos)) 8)))
+                 (let ((syntax (syntax-after blinkpos)))
+                   (and (consp syntax)
+                        (eq (syntax-class syntax) 4)
+                        (cdr syntax))))))
+      (cond
+       ;; isdollar is for:
+       ;; http://lists.gnu.org/archive/html/emacs-devel/2007-10/msg00871.html
+       ((not (or (and isdollar blinkpos)
+                 (and atdollar (not blinkpos)) ; see below
+                 (eq matching-paren (char-before oldpos))
+                 ;; The cdr might hold a new paren-class info rather than
+                 ;; a matching-char info, in which case the two CDRs
+                 ;; should match.
+                 (eq matching-paren (cdr (syntax-after (1- oldpos))))))
+        (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")))
+       ((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.
+        (and blink-matching-paren-on-screen
+             (not show-paren-mode)
+             (save-excursion
+               (goto-char blinkpos)
+               (sit-for blink-matching-delay))))
+       (t
+        (save-excursion
+          (goto-char blinkpos)
+          (let ((open-paren-line-string
+                 ;; Show what precedes the open in its line, if anything.
+                 (cond
+                  ((save-excursion (skip-chars-backward " \t") (not (bolp)))
+                   (buffer-substring (line-beginning-position)
+                                     (1+ blinkpos)))
+                  ;; Show what follows the open in its line, if anything.
+                  ((save-excursion
+                     (forward-char 1)
+                     (skip-chars-forward " \t")
+                     (not (eolp)))
+                   (buffer-substring blinkpos
+                                     (line-end-position)))
+                  ;; Otherwise show the previous nonblank line,
+                  ;; if there is one.
+                  ((save-excursion (skip-chars-backward "\n \t") (not (bobp)))
+                   (concat
+                    (buffer-substring (progn
+                                        (skip-chars-backward "\n \t")
+                                        (line-beginning-position))
+                                      (progn (end-of-line)
+                                             (skip-chars-backward " \t")
+                                             (point)))
+                    ;; Replace the newline and other whitespace with `...'.
+                    "..."
+                    (buffer-substring blinkpos (1+ blinkpos))))
+                  ;; There is nothing to show except the char itself.
+                  (t (buffer-substring blinkpos (1+ blinkpos))))))
+            (message "Matches %s"
+                     (substring-no-properties open-paren-line-string)))))))))
+
+;; Turned off because it makes dbx bomb out.
 (setq blink-paren-function 'blink-matching-open)
 \f
 ;; This executes C-g typed while Emacs is waiting for a command.
@@ -4960,7 +5162,7 @@ With prefix argument N, move N items (negative N means move backward)."
 These functions are called in order with four arguments:
 CHOICE - the string to insert in the buffer,
 BUFFER - the buffer in which the choice should be inserted,
-MINI-P - non-nil iff BUFFER is a minibuffer, and
+MINI-P - non-nil if BUFFER is a minibuffer, and
 BASE-SIZE - the number of characters in BUFFER before
 the string being completed.
 
@@ -5246,10 +5448,10 @@ PREFIX is the string that represents this modifier in an event type symbol."
 \f
 ;;;; Keypad support.
 
-;;; Make the keypad keys act like ordinary typing keys.  If people add
-;;; bindings for the function key symbols, then those bindings will
-;;; override these, so this shouldn't interfere with any existing
-;;; bindings.
+;; Make the keypad keys act like ordinary typing keys.  If people add
+;; bindings for the function key symbols, then those bindings will
+;; override these, so this shouldn't interfere with any existing
+;; bindings.
 
 ;; Also tell read-char how to handle these keys.
 (mapc
@@ -5375,13 +5577,13 @@ after it has been set up properly in other respects."
       (funcall mode)
 
       ;; Set up other local variables.
-      (mapcar (lambda (v)
-               (condition-case ()      ;in case var is read-only
-                   (if (symbolp v)
-                       (makunbound v)
-                     (set (make-local-variable (car v)) (cdr v)))
-                 (error nil)))
-             lvars)
+      (mapc (lambda (v)
+             (condition-case ()        ;in case var is read-only
+                 (if (symbolp v)
+                     (makunbound v)
+                   (set (make-local-variable (car v)) (cdr v)))
+               (error nil)))
+           lvars)
 
       ;; Run any hooks (typically set up by the major mode
       ;; for cloning to work properly).
@@ -5443,36 +5645,33 @@ front of the list of recently selected ones."
 \f
 ;;; Handling of Backspace and Delete keys.
 
-(defcustom normal-erase-is-backspace
-  (and (not noninteractive)
-       (or (memq system-type '(ms-dos windows-nt))
-          (eq window-system 'mac)
-          (and (memq window-system '(x))
-               (fboundp 'x-backspace-delete-keys-p)
-               (x-backspace-delete-keys-p))
-          ;; If the terminal Emacs is running on has erase char
-          ;; set to ^H, use the Backspace key for deleting
-          ;; backward and, and the Delete key for deleting forward.
-          (and (null window-system)
-               (eq tty-erase-char ?\^H))))
-  "If non-nil, Delete key deletes forward and Backspace key deletes backward.
-
-On window systems, the default value of this option is chosen
-according to the keyboard used.  If the keyboard has both a Backspace
-key and a Delete key, and both are mapped to their usual meanings, the
-option's default value is set to t, so that Backspace can be used to
-delete backward, and Delete can be used to delete forward.
-
-If not running under a window system, customizing this option accomplishes
-a similar effect by mapping C-h, which is usually generated by the
-Backspace key, to DEL, and by mapping DEL to C-d via
-`keyboard-translate'.  The former functionality of C-h is available on
-the F1 key.  You should probably not use this setting if you don't
-have both Backspace, Delete and F1 keys.
+(defcustom normal-erase-is-backspace 'maybe
+  "Set the default behaviour of the Delete and Backspace keys.
+
+If set to t, Delete key deletes forward and Backspace key deletes
+backward.
+
+If set to nil, both Delete and Backspace keys delete backward.
+
+If set to 'maybe (which is the default), Emacs automatically
+selects a behaviour.  On window systems, the behaviour depends on
+the keyboard used.  If the keyboard has both a Backspace key and
+a Delete key, and both are mapped to their usual meanings, the
+option's default value is set to t, so that Backspace can be used
+to delete backward, and Delete can be used to delete forward.
+
+If not running under a window system, customizing this option
+accomplishes a similar effect by mapping C-h, which is usually
+generated by the Backspace key, to DEL, and by mapping DEL to C-d
+via `keyboard-translate'.  The former functionality of C-h is
+available on the F1 key.  You should probably not use this
+setting if you don't have both Backspace, Delete and F1 keys.
 
 Setting this variable with setq doesn't take effect.  Programmatically,
 call `normal-erase-is-backspace-mode' (which see) instead."
-  :type 'boolean
+  :type '(choice (const :tag "Off" nil)
+                (const :tag "Maybe" maybe)
+                (other :tag "On" t))
   :group 'editing-basics
   :version "21.1"
   :set (lambda (symbol value)
@@ -5482,17 +5681,37 @@ call `normal-erase-is-backspace-mode' (which see) instead."
             (normal-erase-is-backspace-mode (or value 0))
           (set-default symbol value))))
 
+(defun normal-erase-is-backspace-setup-frame (&optional frame)
+  "Set up `normal-erase-is-backspace-mode' on FRAME, if necessary."
+  (unless frame (setq frame (selected-frame)))
+  (with-selected-frame frame
+    (unless (terminal-parameter nil 'normal-erase-is-backspace)
+      (normal-erase-is-backspace-mode
+       (if (if (eq normal-erase-is-backspace 'maybe)
+               (and (not noninteractive)
+                    (or (memq system-type '(ms-dos windows-nt))
+                        (eq window-system 'mac)
+                        (and (memq window-system '(x))
+                             (fboundp 'x-backspace-delete-keys-p)
+                             (x-backspace-delete-keys-p))
+                        ;; If the terminal Emacs is running on has erase char
+                        ;; set to ^H, use the Backspace key for deleting
+                        ;; backward, and the Delete key for deleting forward.
+                        (and (null window-system)
+                             (eq tty-erase-char ?\^H))))
+             normal-erase-is-backspace)
+           1 0)))))
 
 (defun normal-erase-is-backspace-mode (&optional arg)
   "Toggle the Erase and Delete mode of the Backspace and Delete keys.
 
 With numeric arg, turn the mode on if and only if ARG is positive.
 
-On window systems, when this mode is on, Delete is mapped to C-d and
-Backspace is mapped to DEL; when this mode is off, both Delete and
-Backspace are mapped to DEL.  (The remapping goes via
-`function-key-map', so binding Delete or Backspace in the global or
-local keymap will override that.)
+On window systems, when this mode is on, Delete is mapped to C-d
+and Backspace is mapped to DEL; when this mode is off, both
+Delete and Backspace are mapped to DEL.  (The remapping goes via
+`local-function-key-map', so binding Delete or Backspace in the
+global or local keymap will override that.)
 
 In addition, on window systems, the bindings of C-Delete, M-Delete,
 C-M-Delete, C-Backspace, M-Backspace, and C-M-Backspace are changed in
@@ -5514,61 +5733,65 @@ have both Backspace, Delete and F1 keys.
 
 See also `normal-erase-is-backspace'."
   (interactive "P")
-  (setq normal-erase-is-backspace
-       (if arg
-           (> (prefix-numeric-value arg) 0)
-         (not normal-erase-is-backspace)))
-
-  (cond ((or (memq window-system '(x w32 mac pc))
-            (memq system-type '(ms-dos windows-nt)))
-        (let ((bindings
-               `(([C-delete] [C-backspace])
-                 ([M-delete] [M-backspace])
-                 ([C-M-delete] [C-M-backspace])
-                 (,esc-map
-                  [C-delete] [C-backspace])))
-              (old-state (lookup-key function-key-map [delete])))
-
-          (if normal-erase-is-backspace
+  (let ((enabled (or (and arg (> (prefix-numeric-value arg) 0))
+                    (and (not arg)
+                         (not (eq 1 (terminal-parameter
+                                     nil 'normal-erase-is-backspace)))))))
+    (set-terminal-parameter nil 'normal-erase-is-backspace
+                           (if enabled 1 0))
+
+    (cond ((or (memq window-system '(x w32 mac pc))
+              (memq system-type '(ms-dos windows-nt)))
+          (let* ((bindings
+                  `(([C-delete] [C-backspace])
+                    ([M-delete] [M-backspace])
+                    ([C-M-delete] [C-M-backspace])
+                    (,esc-map
+                     [C-delete] [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 [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)))))))
+         (t
+          (if enabled
               (progn
-                (define-key function-key-map [delete] [?\C-d])
-                (define-key function-key-map [kp-delete] [?\C-d])
-                (define-key function-key-map [backspace] [?\C-?]))
-            (define-key function-key-map [delete] [?\C-?])
-            (define-key function-key-map [kp-delete] [?\C-?])
-            (define-key function-key-map [backspace] [?\C-?]))
-
-          ;; Maybe swap bindings of C-delete and C-backspace, etc.
-          (unless (equal old-state (lookup-key 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)))))))
-        (t
-         (if normal-erase-is-backspace
-             (progn
-               (keyboard-translate ?\C-h ?\C-?)
-               (keyboard-translate ?\C-? ?\C-d))
-           (keyboard-translate ?\C-h ?\C-h)
-           (keyboard-translate ?\C-? ?\C-?))))
-
-  (run-hooks 'normal-erase-is-backspace-hook)
-  (if (interactive-p)
-      (message "Delete key deletes %s"
-              (if normal-erase-is-backspace "forward" "backward"))))
+                (keyboard-translate ?\C-h ?\C-?)
+                (keyboard-translate ?\C-? ?\C-d))
+            (keyboard-translate ?\C-h ?\C-h)
+            (keyboard-translate ?\C-? ?\C-?))))
+
+    (run-hooks 'normal-erase-is-backspace-hook)
+    (if (interactive-p)
+       (message "Delete key deletes %s"
+                (if (terminal-parameter nil 'normal-erase-is-backspace)
+                    "forward" "backward")))))
 \f
 (defvar vis-mode-saved-buffer-invisibility-spec nil
   "Saved value of `buffer-invisibility-spec' when Visible mode is on.")
 
 (define-minor-mode visible-mode
   "Toggle Visible mode.
-With argument ARG turn Visible mode on iff ARG is positive.
+With argument ARG turn Visible mode on if ARG is positive, otherwise
+turn it off.
 
 Enabling Visible mode makes all invisible text temporarily visible.
 Disabling Visible mode turns off that effect.  Visible mode
@@ -5604,6 +5827,58 @@ works by saving the value of `buffer-invisibility-spec' and setting it to nil."
 ;      'insert-in-front-hooks '(minibuffer-prompt-insertion)))
 ;
 
+\f
+;;;; Problematic external packages.
+
+;; rms says this should be done by specifying symbols that define
+;; versions together with bad values.  This is therefore not as
+;; flexible as it could be.  See the thread:
+;; http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00300.html
+(defconst bad-packages-alist
+  ;; Not sure exactly which semantic versions have problems.
+  ;; Definitely 2.0pre3, probably all 2.0pre's before this.
+  '((semantic semantic-version "\\`2\\.0pre[1-3]\\'"
+              "The version of `semantic' loaded does not work in Emacs 22.
+It can cause constant high CPU load.
+Upgrade to at least Semantic 2.0pre4 (distributed with CEDET 1.0pre4).")
+    ;; CUA-mode does not work with GNU Emacs version 22.1 and newer.
+    ;; Except for version 1.2, all of the 1.x and 2.x version of cua-mode
+    ;; provided the `CUA-mode' feature.  Since this is no longer true,
+    ;; we can warn the user if the `CUA-mode' feature is ever provided.
+    (CUA-mode t nil
+"CUA-mode is now part of the standard GNU Emacs distribution,
+so you can now enable CUA via the Options menu or by customizing `cua-mode'.
+
+You have loaded an older version of CUA-mode which does not work
+correctly with this version of Emacs.  You should remove the old
+version and use the one distributed with Emacs."))
+  "Alist of packages known to cause problems in this version of Emacs.
+Each element has the form (PACKAGE SYMBOL REGEXP STRING).
+PACKAGE is either a regular expression to match file names, or a
+symbol (a feature name); see the documentation of
+`after-load-alist', to which this variable adds functions.
+SYMBOL is either the name of a string variable, or `t'.  Upon
+loading PACKAGE, if SYMBOL is t or matches REGEXP, display a
+warning using STRING as the message.")
+
+(defun bad-package-check (package)
+  "Run a check using the element from `bad-packages-alist' matching PACKAGE."
+  (condition-case nil
+      (let* ((list (assoc package bad-packages-alist))
+             (symbol (nth 1 list)))
+        (and list
+             (boundp symbol)
+             (or (eq symbol t)
+                 (and (stringp (setq symbol (eval symbol)))
+                      (string-match (nth 2 list) symbol)))
+             (display-warning :warning (nth 3 list))))
+    (error nil)))
+
+(mapc (lambda (elem)
+        (eval-after-load (car elem) `(bad-package-check ',(car elem))))
+      bad-packages-alist)
+
+
 (provide 'simple)
 
 ;; arch-tag: 24af67c0-2a49-44f6-b3b1-312d8b570dfd