(rmail-forward-separator-regex): Fix typo in docstring.
[bpt/emacs.git] / lisp / simple.el
index e7498d6..ba661e5 100644 (file)
@@ -1,7 +1,7 @@
 ;;; simple.el --- basic editing commands for Emacs
 
-;; Copyright (C) 1985, 86, 87, 93, 94, 95, 96, 97, 98, 99,
-;;               2000, 01, 02, 03, 04
+;; Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+;;               2000, 2001, 2002, 2003, 2004, 2005
 ;;        Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
   (autoload 'widget-convert "wid-edit")
   (autoload 'shell-mode "shell"))
 
+(defcustom idle-update-delay 0.5
+  "*Idle time delay before updating various things on the screen.
+Various Emacs features that update auxiliary information when point moves
+wait this many seconds after Emacs becomes idle before doing an update."
+  :type 'number
+  :group 'display
+  :version "22.1")
 
 (defgroup killing nil
   "Killing and yanking commands."
@@ -44,8 +51,6 @@
   "Highlight (un)matching of parens and expressions."
   :group 'matching)
 
-(define-key global-map [?\C-x right] 'next-buffer)
-(define-key global-map [?\C-x left] 'prev-buffer)
 (defun next-buffer ()
   "Switch to the next buffer in cyclic order."
   (interactive)
     (switch-to-buffer found)))
 \f
 ;;; next-error support framework
+
+(defgroup next-error nil
+  "next-error support framework."
+  :group 'compilation
+  :version "22.1")
+
+(defface next-error
+  '((t (:inherit region)))
+  "Face used to highlight next error locus."
+  :group 'next-error
+  :version "22.1")
+
+(defcustom next-error-highlight 0.1
+  "*Highlighting of locations in selected source buffers.
+If number, highlight the locus in next-error face for given time in seconds.
+If t, use persistent overlays fontified in next-error face.
+If nil, don't highlight the locus in the source buffer.
+If `fringe-arrow', indicate the locus by the fringe arrow."
+  :type '(choice (number :tag "Delay")
+                 (const :tag "Persistent overlay" t)
+                 (const :tag "No highlighting" nil)
+                 (const :tag "Fringe arrow" 'fringe-arrow))
+  :group 'next-error
+  :version "22.1")
+
+(defcustom next-error-highlight-no-select 0.1
+  "*Highlighting of locations in non-selected source buffers.
+If number, highlight the locus in next-error face for given time in seconds.
+If t, use persistent overlays fontified in next-error face.
+If nil, don't highlight the locus in the source buffer.
+If `fringe-arrow', indicate the locus by the fringe arrow."
+  :type '(choice (number :tag "Delay")
+                 (const :tag "Persistent overlay" t)
+                 (const :tag "No highlighting" nil)
+                 (const :tag "Fringe arrow" 'fringe-arrow))
+  :group 'next-error
+  :version "22.1")
+
+(defvar next-error-highlight-timer nil)
+
+(defvar next-error-overlay-arrow-position nil)
+(put 'next-error-overlay-arrow-position 'overlay-arrow-string "=>")
+(add-to-list 'overlay-arrow-variable-list 'next-error-overlay-arrow-position)
+
 (defvar next-error-last-buffer nil
   "The most recent next-error buffer.
 A buffer becomes most recent when its compilation, grep, or
@@ -85,54 +134,88 @@ to navigate in it.")
 
 (make-variable-buffer-local 'next-error-function)
 
-(defsubst next-error-buffer-p (buffer &optional extra-test)
-  "Test if BUFFER is a next-error capable buffer."
-  (with-current-buffer buffer
-    (or (and extra-test (funcall extra-test))
-       next-error-function)))
-
-(defun next-error-find-buffer (&optional other-buffer extra-test)
-  "Return a next-error capable buffer."
+(defsubst next-error-buffer-p (buffer
+                              &optional avoid-current
+                              extra-test-inclusive
+                              extra-test-exclusive)
+  "Test if BUFFER is a next-error capable buffer.
+
+If AVOID-CURRENT is non-nil, treat the current buffer
+as an absolute last resort only.
+
+The function EXTRA-TEST-INCLUSIVE, if non-nil, is called in each buffer
+that normally would not qualify.  If it returns t, the buffer
+in question is treated as usable.
+
+The function EXTRA-TEST-EXCLUSIVE, if non-nil is called in each buffer
+that would normally be considered usable.  if it returns nil,
+that buffer is rejected."
+  (and (buffer-name buffer)            ;First make sure it's live.
+       (not (and avoid-current (eq buffer (current-buffer))))
+       (with-current-buffer buffer
+        (if next-error-function   ; This is the normal test.
+            ;; Optionally reject some buffers.
+            (if extra-test-exclusive
+                (funcall extra-test-exclusive)
+              t)
+          ;; Optionally accept some other buffers.
+          (and extra-test-inclusive
+               (funcall extra-test-inclusive))))))
+
+(defun next-error-find-buffer (&optional avoid-current
+                                        extra-test-inclusive
+                                        extra-test-exclusive)
+  "Return a next-error capable buffer.
+If AVOID-CURRENT is non-nil, treat the current buffer
+as an absolute last resort only.
+
+The function EXTRA-TEST-INCLUSIVE, if non-nil, is called in each buffers
+that normally would not qualify.  If it returns t, the buffer
+in question is treated as usable.
+
+The function EXTRA-TEST-EXCLUSIVE, if non-nil is called in each buffer
+that would normally be considered usable.  If it returns nil,
+that buffer is rejected."
   (or
    ;; 1. If one window on the selected frame displays such buffer, return it.
    (let ((window-buffers
           (delete-dups
            (delq nil (mapcar (lambda (w)
                                (if (next-error-buffer-p
-                                    (window-buffer w) extra-test)
+                                   (window-buffer w)
+                                    avoid-current
+                                    extra-test-inclusive extra-test-exclusive)
                                    (window-buffer w)))
                              (window-list))))))
-     (if other-buffer
-         (setq window-buffers (delq (current-buffer) window-buffers)))
      (if (eq (length window-buffers) 1)
          (car window-buffers)))
-   ;; 2. If next-error-last-buffer is set to a live buffer, use that.
+   ;; 2. If next-error-last-buffer is an acceptable buffer, use that.
    (if (and next-error-last-buffer
-            (buffer-name next-error-last-buffer)
-            (next-error-buffer-p next-error-last-buffer extra-test)
-            (or (not other-buffer)
-                (not (eq next-error-last-buffer (current-buffer)))))
+            (next-error-buffer-p next-error-last-buffer avoid-current
+                                 extra-test-inclusive extra-test-exclusive))
        next-error-last-buffer)
-   ;; 3. If the current buffer is a next-error capable buffer, return it.
-   (if (and (not other-buffer)
-            (next-error-buffer-p (current-buffer) extra-test))
+   ;; 3. If the current buffer is acceptable, choose it.
+   (if (next-error-buffer-p (current-buffer) avoid-current
+                           extra-test-inclusive extra-test-exclusive)
        (current-buffer))
-   ;; 4. Look for a next-error capable buffer in a buffer list.
+   ;; 4. Look for any acceptable buffer.
    (let ((buffers (buffer-list)))
      (while (and buffers
-                 (or (not (next-error-buffer-p (car buffers) extra-test))
-                     (and other-buffer (eq (car buffers) (current-buffer)))))
+                 (not (next-error-buffer-p
+                      (car buffers) avoid-current
+                      extra-test-inclusive extra-test-exclusive)))
        (setq buffers (cdr buffers)))
-     (if buffers
-         (car buffers)
-       (or (and other-buffer
-                (next-error-buffer-p (current-buffer) extra-test)
-                ;; The current buffer is a next-error capable buffer.
-                (progn
-                  (if other-buffer
-                      (message "This is the only next-error capable buffer"))
-                  (current-buffer)))
-           (error "No next-error capable buffer found"))))))
+     (car buffers))
+   ;; 5. Use the current buffer as a last resort if it qualifies,
+   ;; even despite AVOID-CURRENT.
+   (and avoid-current
+       (next-error-buffer-p (current-buffer) nil
+                            extra-test-inclusive extra-test-exclusive)
+       (progn
+         (message "This is the only next-error capable buffer")
+         (current-buffer)))
+   ;; 6. Give up.
+   (error "No next-error capable buffer found")))
 
 (defun next-error (&optional arg reset)
   "Visit next next-error message and corresponding source code.
@@ -173,8 +256,6 @@ See variables `compilation-parse-errors-function' and
 (defalias 'goto-next-locus 'next-error)
 (defalias 'next-match 'next-error)
 
-(define-key ctl-x-map "`" 'next-error)
-
 (defun previous-error (&optional n)
   "Visit previous next-error message and corresponding source code.
 
@@ -213,43 +294,6 @@ select the source buffer."
   (interactive "p")
   (next-error-no-select (- (or n 1))))
 
-(defgroup next-error nil
-  "next-error support framework."
-  :group 'compilation
-  :version "21.4")
-
-(defface next-error
-  '((t (:inherit region)))
-  "Face used to highlight next error locus."
-  :group 'next-error
-  :version "21.4")
-
-(defcustom next-error-highlight 0.1
-  "*Highlighting of locations in selected source buffers.
-If number, highlight the locus in next-error face for given time in seconds.
-If t, use persistent overlays fontified in next-error face.
-If nil, don't highlight the locus in the source buffer.
-If `fringe-arrow', indicate the locus by the fringe arrow."
-  :type '(choice (number :tag "Delay")
-                 (const :tag "Persistent overlay" t)
-                 (const :tag "No highlighting" nil)
-                 (const :tag "Fringe arrow" 'fringe-arrow))
-  :group 'next-error
-  :version "21.4")
-
-(defcustom next-error-highlight-no-select 0.1
-  "*Highlighting of locations in non-selected source buffers.
-If number, highlight the locus in next-error face for given time in seconds.
-If t, use persistent overlays fontified in next-error face.
-If nil, don't highlight the locus in the source buffer.
-If `fringe-arrow', indicate the locus by the fringe arrow."
-  :type '(choice (number :tag "Delay")
-                 (const :tag "Persistent overlay" t)
-                 (const :tag "No highlighting" nil)
-                 (const :tag "Fringe arrow" 'fringe-arrow))
-  :group 'next-error
-  :version "21.4")
-
 ;;; Internal variable for `next-error-follow-mode-post-command-hook'.
 (defvar next-error-follow-last-line nil)
 
@@ -258,7 +302,7 @@ If `fringe-arrow', indicate the locus by the fringe arrow."
 When turned on, cursor motion in the compilation, grep, occur or diff
 buffer causes automatic display of the corresponding source code
 location."
-  nil " Fol" nil
+  :group 'next-error :init-value " Fol"
   (if (not next-error-follow-minor-mode)
       (remove-hook 'post-command-hook 'next-error-follow-mode-post-command-hook t)
     (add-hook 'post-command-hook 'next-error-follow-mode-post-command-hook nil t)
@@ -282,7 +326,8 @@ location."
   "Major mode not specialized for anything in particular.
 Other major modes are defined by comparison with this one."
   (interactive)
-  (kill-all-local-variables))
+  (kill-all-local-variables)
+  (run-hooks 'after-change-major-mode-hook))
 
 ;; Making and deleting lines.
 
@@ -611,24 +656,22 @@ If BACKWARD-ONLY is non-nil, only delete spaces before point."
        (skip-chars-backward " \t")
        (constrain-to-field nil orig-pos)))))
 
-(defun just-one-space ()
-  "Delete all spaces and tabs around point, leaving one space."
-  (interactive "*")
+(defun just-one-space (&optional n)
+  "Delete all spaces and tabs around point, leaving one space (or N spaces)."
+  (interactive "*p")
   (let ((orig-pos (point)))
     (skip-chars-backward " \t")
     (constrain-to-field nil orig-pos)
-    (if (= (following-char) ? )
-       (forward-char 1)
-      (insert ? ))
+    (dotimes (i (or n 1))
+      (if (= (following-char) ?\ )
+         (forward-char 1)
+       (insert ?\ )))
     (delete-region
      (point)
      (progn
        (skip-chars-forward " \t")
        (constrain-to-field nil orig-pos t)))))
 \f
-(defvar inhibit-mark-movement nil
-  "If non-nil, \\[beginning-of-buffer] and \\[end-of-buffer] does not set the mark.")
-
 (defun beginning-of-buffer (&optional arg)
   "Move point to the beginning of the buffer; leave mark at previous position.
 With \\[universal-argument] prefix, do not set mark at previous position.
@@ -640,8 +683,9 @@ of the accessible part of the buffer.
 Don't use this command in Lisp programs!
 \(goto-char (point-min)) is faster and avoids clobbering the mark."
   (interactive "P")
-  (unless (or inhibit-mark-movement (consp arg))
-    (push-mark))
+  (or (consp arg)
+      (and transient-mark-mode mark-active)
+      (push-mark))
   (let ((size (- (point-max) (point-min))))
     (goto-char (if (and arg (not (consp arg)))
                   (+ (point-min)
@@ -664,8 +708,9 @@ of the accessible part of the buffer.
 Don't use this command in Lisp programs!
 \(goto-char (point-max)) is faster and avoids clobbering the mark."
   (interactive "P")
-  (unless (or inhibit-mark-movement (consp arg))
-    (push-mark))
+  (or (consp arg)
+      (and transient-mark-mode mark-active)
+      (push-mark))
   (let ((size (- (point-max) (point-min))))
     (goto-char (if (and arg (not (consp arg)))
                   (- (point-max)
@@ -697,10 +742,49 @@ that uses or sets the mark."
 
 ;; Counting lines, one way or another.
 
-(defun goto-line (arg)
-  "Goto line ARG, counting from line 1 at beginning of buffer."
-  (interactive "NGoto line: ")
-  (setq arg (prefix-numeric-value arg))
+(defun goto-line (arg &optional buffer)
+  "Goto line ARG, counting from line 1 at beginning of buffer.
+Normally, move point in the current buffer.
+With just \\[universal-argument] as argument, move point in the most recently
+displayed other buffer, and switch to it.  When called from Lisp code,
+the optional argument BUFFER specifies a buffer to switch to.
+
+If there's a number in the buffer at point, it is the default for ARG."
+  (interactive
+   (if (and current-prefix-arg (not (consp current-prefix-arg)))
+       (list (prefix-numeric-value current-prefix-arg))
+     ;; Look for a default, a number in the buffer at point.
+     (let* ((default
+             (save-excursion
+               (skip-chars-backward "0-9")
+               (if (looking-at "[0-9]")
+                   (buffer-substring-no-properties
+                    (point)
+                    (progn (skip-chars-forward "0-9")
+                           (point))))))
+           ;; Decide if we're switching buffers.
+           (buffer
+            (if (consp current-prefix-arg)
+                (other-buffer (current-buffer) t)))
+           (buffer-prompt
+            (if buffer
+                (concat " in " (buffer-name buffer))
+              "")))
+       ;; Read the argument, offering that number (if any) as default.
+       (list (read-from-minibuffer (format (if default "Goto line%s (%s): "
+                                            "Goto line%s: ")
+                                          buffer-prompt
+                                          default)
+                                  nil nil t
+                                  'minibuffer-history
+                                  default)
+            buffer))))
+  ;; Switch to the desired buffer, one way or another.
+  (if buffer
+      (let ((window (get-buffer-window buffer)))
+       (if window (select-window window)
+         (switch-to-buffer-other-window buffer))))
+  ;; Move to the specified line number in that buffer.
   (save-restriction
     (widen)
     (goto-char 1)
@@ -717,7 +801,7 @@ that uses or sets the mark."
 (defun what-line ()
   "Print the current buffer line number and narrowed line number of point."
   (interactive)
-  (let ((opoint (point)) (start (point-min))
+  (let ((start (point-min))
        (n (line-number-at-pos)))
     (if (= start 1)
        (message "Line %d" n)
@@ -836,21 +920,21 @@ in *Help* buffer.  See also the command `describe-char'."
 (defvar read-expression-history nil)
 
 (defcustom eval-expression-print-level 4
-  "*Value to use for `print-level' when printing value in `eval-expression'.
+  "Value for `print-level' while printing value in `eval-expression'.
 A value of nil means no limit."
   :group 'lisp
   :type '(choice (const :tag "No Limit" nil) integer)
   :version "21.1")
 
 (defcustom eval-expression-print-length 12
-  "*Value to use for `print-length' when printing value in `eval-expression'.
+  "Value for `print-length' while printing value in `eval-expression'.
 A value of nil means no limit."
   :group 'lisp
   :type '(choice (const :tag "No Limit" nil) integer)
   :version "21.1")
 
 (defcustom eval-expression-debug-on-error t
-  "*Non-nil means set `debug-on-error' when evaluating in `eval-expression'.
+  "If non-nil set `debug-on-error' to t in `eval-expression'.
 If nil, don't change the value of `debug-on-error'."
   :group 'lisp
   :type 'boolean
@@ -864,9 +948,9 @@ display the result of expression evaluation."
   (if (and (integerp value)
            (or (not (memq this-command '(eval-last-sexp eval-print-last-sexp)))
                (eq this-command last-command)
-               (and (boundp 'edebug-active) edebug-active)))
+               (if (boundp 'edebug-active) edebug-active)))
       (let ((char-string
-             (if (or (and (boundp 'edebug-active) edebug-active)
+             (if (or (if (boundp 'edebug-active) edebug-active)
                      (memq this-command '(eval-last-sexp eval-print-last-sexp)))
                  (prin1-char value))))
         (if char-string
@@ -1095,11 +1179,13 @@ makes the search case-sensitive."
                                        nil
                                        minibuffer-local-map
                                        nil
-                                       'minibuffer-history-search-history)))
+                                       'minibuffer-history-search-history
+                                       (car minibuffer-history-search-history))))
      ;; Use the last regexp specified, by default, if input is empty.
      (list (if (string= regexp "")
-              (setcar minibuffer-history-search-history
-                      (nth 1 minibuffer-history-search-history))
+              (if minibuffer-history-search-history
+                  (car minibuffer-history-search-history)
+                (error "No previous history search regexp"))
             regexp)
           (prefix-numeric-value current-prefix-arg))))
   (previous-matching-history-element regexp (- n)))
@@ -1189,7 +1275,9 @@ Return 0 if current buffer is not a mini-buffer."
 (defalias 'advertised-undo 'undo)
 
 (defconst undo-equiv-table (make-hash-table :test 'eq :weakness t)
-  "Table mapping redo records to the corresponding undo one.")
+  "Table mapping redo records to the corresponding undo one.
+A redo record for undo-in-region maps to t.
+A redo record for ordinary undo maps to the following (earlier) undo.")
 
 (defvar undo-in-region nil
   "Non-nil if `pending-undo-list' is not just a tail of `buffer-undo-list'.")
@@ -1197,6 +1285,10 @@ Return 0 if current buffer is not a mini-buffer."
 (defvar undo-no-redo nil
   "If t, `undo' doesn't go through redo entries.")
 
+(defvar pending-undo-list nil
+  "Within a run of consecutive undo commands, list remaining to be undone.
+t if we undid all the way to the end of it.")
+
 (defun undo (&optional arg)
   "Undo some previous changes.
 Repeat this command to undo more changes.
@@ -1219,7 +1311,16 @@ as an argument limits undo to changes within the current region."
     ;; So set `this-command' to something other than `undo'.
     (setq this-command 'undo-start)
 
-    (unless (eq last-command 'undo)
+    (unless (and (eq last-command 'undo)
+                (or (eq pending-undo-list t)
+                    ;; If something (a timer or filter?) changed the buffer
+                    ;; since the previous command, don't continue the undo seq.
+                    (let ((list buffer-undo-list))
+                      (while (eq (car list) nil)
+                        (setq list (cdr list)))
+                      ;; If the last undo record made was made by undo
+                      ;; it shows nothing else happened in between.
+                      (gethash list undo-equiv-table))))
       (setq undo-in-region
            (if transient-mark-mode mark-active (and arg (not (numberp arg)))))
       (if undo-in-region
@@ -1236,7 +1337,7 @@ as an argument limits undo to changes within the current region."
          (message (if undo-in-region
                       (if equiv "Redo in region!" "Undo in region!")
                     (if equiv "Redo!" "Undo!"))))
-      (when (and equiv undo-no-redo)
+      (when (and (consp equiv) undo-no-redo)
        ;; The equiv entry might point to another redo record if we have done
        ;; undo-redo-undo-redo-... so skip to the very last equiv.
        (while (let ((next (gethash equiv undo-equiv-table)))
@@ -1247,10 +1348,13 @@ as an argument limits undo to changes within the current region."
         (prefix-numeric-value arg)
        1))
     ;; Record the fact that the just-generated undo records come from an
-    ;; undo operation, so we can skip them later on.
+    ;; undo operation--that is, they are redo records.
+    ;; 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.
-    (unless undo-in-region
-      (puthash buffer-undo-list pending-undo-list undo-equiv-table))
+    (puthash buffer-undo-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)
@@ -1271,10 +1375,18 @@ as an argument limits undo to changes within the current region."
              (setq tail (cdr tail)))
            (setq tail nil)))
        (setq prev tail tail (cdr tail))))
-
+    ;; Record what the current undo list says,
+    ;; so the next command can tell if the buffer was modified in between.
     (and modified (not (buffer-modified-p))
         (delete-auto-save-file-if-necessary recent-save))))
 
+(defun buffer-disable-undo (&optional buffer)
+  "Make BUFFER stop keeping undo information.
+No argument or nil as argument means do this for the current buffer."
+  (interactive)
+  (with-current-buffer (if buffer (get-buffer buffer) (current-buffer))
+    (setq buffer-undo-list t)))
+
 (defun undo-only (&optional arg)
   "Undo some previous changes.
 Repeat this command to undo more changes.
@@ -1282,12 +1394,6 @@ A numeric argument serves as a repeat count.
 Contrary to `undo', this will not redo a previous undo."
   (interactive "*p")
   (let ((undo-no-redo t)) (undo arg)))
-;; Richard said that we should not use C-x <uppercase letter> and I have
-;; no idea whereas to bind it.  Any suggestion welcome.  -stef
-;; (define-key ctl-x-map "U" 'undo-only)
-
-(defvar pending-undo-list nil
-  "Within a run of consecutive undo commands, list remaining to be undone.")
 
 (defvar undo-in-progress nil
   "Non-nil while performing an undo.
@@ -1297,12 +1403,14 @@ Some change-hooks test this variable to do something different.")
   "Undo back N undo-boundaries beyond what was already undone recently.
 Call `undo-start' to get ready to undo recent changes,
 then call `undo-more' one or more times to undo them."
-  (or pending-undo-list
+  (or (listp pending-undo-list)
       (error (format "No further undo information%s"
                     (if (and transient-mark-mode mark-active)
                         " for region" ""))))
   (let ((undo-in-progress t))
-    (setq pending-undo-list (primitive-undo count pending-undo-list))))
+    (setq pending-undo-list (primitive-undo count pending-undo-list))
+    (if (null pending-undo-list)
+       (setq pending-undo-list t))))
 
 ;; Deep copy of a list
 (defun undo-copy-list (list)
@@ -1466,6 +1574,77 @@ is not *inside* the region START...END."
            (t
             '(0 . 0)))
     '(0 . 0)))
+
+(defcustom undo-ask-before-discard t
+  "If non-nil ask about discarding undo info for the current command.
+Normally, Emacs discards the undo info for the current command if
+it exceeds `undo-outer-limit'.  But if you set this option
+non-nil, it asks in the echo area whether to discard the info.
+If you answer no, there a slight risk that Emacs might crash, so
+only do it if you really want to undo the command.
+
+This option is mainly intended for debugging.  You have to be
+careful if you use it for other purposes.  Garbage collection is
+inhibited while the question is asked, meaning that Emacs might
+leak memory.  So you should make sure that you do not wait
+excessively long before answering the question."
+  :type 'boolean
+  :group 'undo
+  :version "22.1")
+
+(defvar undo-extra-outer-limit nil
+  "If non-nil, an extra level of size that's ok in an undo item.
+We don't ask the user about truncating the undo list until the
+current item gets bigger than this amount.
+
+This variable only matters if `undo-ask-before-discard' is non-nil.")
+(make-variable-buffer-local 'undo-extra-outer-limit)
+
+;; When the first undo batch in an undo list is longer than
+;; undo-outer-limit, this function gets called to warn the user that
+;; the undo info for the current command was discarded.  Garbage
+;; collection is inhibited around the call, so it had better not do a
+;; lot of consing.
+(setq undo-outer-limit-function 'undo-outer-limit-truncate)
+(defun undo-outer-limit-truncate (size)
+  (if undo-ask-before-discard
+      (when (or (null undo-extra-outer-limit)
+               (> size undo-extra-outer-limit))
+       ;; Don't ask the question again unless it gets even bigger.
+       ;; This applies, in particular, if the user quits from the question.
+       ;; Such a quit quits out of GC, but something else will call GC
+       ;; again momentarily.  It will call this function again,
+       ;; but we don't want to ask the question again.
+       (setq undo-extra-outer-limit (+ size 50000))
+       (if (let (use-dialog-box track-mouse executing-kbd-macro )
+             (yes-or-no-p (format "Buffer %s undo info is %d bytes long; discard it? "
+                                  (buffer-name) size)))
+           (progn (setq buffer-undo-list nil)
+                  (setq undo-extra-outer-limit nil)
+                  t)
+         nil))
+    (display-warning '(undo discard-info)
+                    (concat
+                     (format "Buffer %s undo info was %d bytes long.\n"
+                             (buffer-name) size)
+                     "The undo info was discarded because it exceeded \
+`undo-outer-limit'.
+
+This is normal if you executed a command that made a huge change
+to the buffer.  In that case, to prevent similar problems in the
+future, set `undo-outer-limit' to a value that is large enough to
+cover the maximum size of normal changes you expect a single
+command to make, but not so large that it might exceed the
+maximum memory allotted to Emacs.
+
+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")
+                    :warning)
+    (setq buffer-undo-list nil)
+    t))
 \f
 (defvar shell-command-history nil
   "History list for some commands that read shell commands.")
@@ -1878,6 +2057,39 @@ specifies the value of ERROR-BUFFER."
     (with-current-buffer
       standard-output
       (call-process shell-file-name nil t nil shell-command-switch command))))
+
+(defun process-file (program &optional infile buffer display &rest args)
+  "Process files synchronously in a separate process.
+Similar to `call-process', but may invoke a file handler based on
+`default-directory'.  The current working directory of the
+subprocess is `default-directory'.
+
+File names in INFILE and BUFFER are handled normally, but file
+names in ARGS should be relative to `default-directory', as they
+are passed to the process verbatim.  \(This is a difference to
+`call-process' which does not support file handlers for INFILE
+and BUFFER.\)
+
+Some file handlers might not support all variants, for example
+they might behave as if DISPLAY was nil, regardless of the actual
+value passed."
+  (let ((fh (find-file-name-handler default-directory 'process-file))
+        lc stderr-file)
+    (unwind-protect
+        (if fh (apply fh 'process-file program infile buffer display args)
+          (when infile (setq lc (file-local-copy infile)))
+          (setq stderr-file (when (and (consp buffer) (stringp (cadr buffer)))
+                              (make-temp-file "emacs")))
+          (prog1
+              (apply 'call-process program
+                     (or lc infile)
+                     (if stderr-file (list (car buffer) stderr-file) buffer)
+                     display args)
+            (when stderr-file (copy-file stderr-file (cadr buffer)))))
+      (when stderr-file (delete-file stderr-file))
+      (when lc (delete-file lc)))))
+
+
 \f
 (defvar universal-argument-map
   (let ((map (make-sparse-keymap)))
@@ -2015,6 +2227,42 @@ These commands include \\[set-mark-command] and \\[start-kbd-macro]."
   (reset-this-command-lengths)
   (restore-overriding-map))
 \f
+(defvar buffer-substring-filters nil
+  "List of filter functions for `filter-buffer-substring'.
+Each function must accept a single argument, a string, and return
+a string.  The buffer substring is passed to the first function
+in the list, and the return value of each function is passed to
+the next.  The return value of the last function is used as the
+return value of `filter-buffer-substring'.
+
+If this variable is nil, no filtering is performed.")
+
+(defun filter-buffer-substring (beg end &optional delete)
+  "Return the buffer substring between BEG and END, after filtering.
+The buffer substring is passed through each of the filter
+functions in `buffer-substring-filters', and the value from the
+last filter function is returned.  If `buffer-substring-filters'
+is nil, the buffer substring is returned unaltered.
+
+If DELETE is non-nil, the text between BEG and END is deleted
+from the buffer.
+
+Point is temporarily set to BEG before calling
+`buffer-substring-filters', in case the functions need to know
+where the text came from.
+
+This function should be used instead of `buffer-substring' or
+`delete-and-extract-region' when you want to allow filtering to
+take place.  For example, major or minor modes can use
+`buffer-substring-filters' to extract characters that are special
+to a buffer, and should not be copied into other buffers."
+  (save-excursion
+    (goto-char beg)
+    (let ((string (if delete (delete-and-extract-region beg end)
+                    (buffer-substring beg end))))
+      (dolist (filter buffer-substring-filters string)
+        (setq string (funcall filter string))))))
+
 ;;;; Window system cut and paste hooks.
 
 (defvar interprogram-cut-function nil
@@ -2191,7 +2439,7 @@ specifies the yank-handler text property to be set on the killed
 text.  See `insert-for-yank'."
   (interactive "r")
   (condition-case nil
-      (let ((string (delete-and-extract-region beg end)))
+      (let ((string (filter-buffer-substring beg end t)))
        (when string                    ;STRING is nil if BEG = END
          ;; Add that string to the kill ring, one way or another.
          (if (eq last-command 'kill-region)
@@ -2227,8 +2475,8 @@ If `interprogram-cut-function' is non-nil, also save the text for a window
 system cut and paste."
   (interactive "r")
   (if (eq last-command 'kill-region)
-      (kill-append (buffer-substring beg end) (< end beg))
-    (kill-new (buffer-substring beg end)))
+      (kill-append (filter-buffer-substring beg end) (< end beg))
+    (kill-new (filter-buffer-substring beg end)))
   (if transient-mark-mode
       (setq deactivate-mark t))
   nil)
@@ -2246,6 +2494,8 @@ 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
+  ;; because the code it controls just gives the user visual feedback.
   (if (interactive-p)
       (let ((other-end (if (= (point) beg) end beg))
            (opoint (point))
@@ -2291,13 +2541,13 @@ The argument is used for internal purposes; do not supply one."
 ;; This is actually used in subr.el but defcustom does not work there.
 (defcustom yank-excluded-properties
   '(read-only invisible intangible field mouse-face help-echo local-map keymap
-    yank-handler)
+    yank-handler follow-link)
   "*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))
   :group 'killing
-  :version "21.4")
+  :version "22.1")
 
 (defvar yank-window-start nil)
 (defvar yank-undo-function nil
@@ -2318,7 +2568,11 @@ With argument N, insert the Nth previous kill.
 If N is negative, this is a more recent kill.
 
 The sequence of kills wraps around, so that after the oldest one
-comes the newest one."
+comes the newest one.
+
+When this command inserts killed text into the buffer, it honors
+`yank-excluded-properties' and `yank-handler' as described in the
+doc string for `insert-for-yank-1', which see."
   (interactive "*p")
   (if (not (eq last-command 'yank))
       (error "Previous command was not a yank"))
@@ -2350,6 +2604,11 @@ killed OR yanked.  Put point at end, and set mark at beginning.
 With just \\[universal-argument] as argument, same but put point at beginning (and mark at end).
 With argument N, reinsert the Nth most recently killed stretch of killed
 text.
+
+When this command inserts killed text into the buffer, it honors
+`yank-excluded-properties' and `yank-handler' as described in the
+doc string for `insert-for-yank-1', which see.
+
 See also the command \\[yank-pop]."
   (interactive "*P")
   (setq yank-window-start (window-start))
@@ -2711,6 +2970,14 @@ START and END specify the portion of the current buffer to be copied."
 (put 'mark-inactive 'error-conditions '(mark-inactive error))
 (put 'mark-inactive 'error-message "The mark is not active now")
 
+(defvar activate-mark-hook nil
+  "Hook run when the mark becomes active.
+It is also run at the end of a command, if the mark is active and
+it is possible that the region may have changed")
+
+(defvar deactivate-mark-hook nil
+  "Hook run when the mark becomes inactive.")
+
 (defun mark (&optional force)
   "Return this buffer's mark value as integer; error if mark inactive.
 If optional argument FORCE is non-nil, access the mark value
@@ -2743,7 +3010,7 @@ the user to see that the mark has moved, and you want the previous
 mark position to be lost.
 
 Normally, when a new mark is set, the old one should go on the stack.
-This is why most applications should use push-mark, not set-mark.
+This is why most applications should use `push-mark', not `set-mark'.
 
 Novice Emacs Lisp programmers often try to use the mark for the wrong
 purposes.  The mark saves a location for the user's convenience.
@@ -2802,6 +3069,7 @@ Display `Mark set' unless the optional second arg NOMSG is non-nil."
     (if (or arg (null mark) (/= mark (point)))
        (push-mark nil nomsg t)
       (setq mark-active t)
+      (run-hooks 'activate-mark-hook)
       (unless nomsg
        (message "Mark activated")))))
 
@@ -2892,10 +3160,10 @@ Does not set point.  Does nothing if mark ring is empty."
   (when mark-ring
     (setq mark-ring (nconc mark-ring (list (copy-marker (mark-marker)))))
     (set-marker (mark-marker) (+ 0 (car mark-ring)) (current-buffer))
-    (deactivate-mark)
     (move-marker (car mark-ring) nil)
     (if (null (mark t)) (ding))
-    (setq mark-ring (cdr mark-ring))))
+    (setq mark-ring (cdr mark-ring)))
+  (deactivate-mark))
 
 (defalias 'exchange-dot-and-mark 'exchange-point-and-mark)
 (defun exchange-point-and-mark (&optional arg)
@@ -2933,13 +3201,21 @@ You can also deactivate the mark by typing \\[keyboard-quit] or
 Many commands change their behavior when Transient Mark mode is in effect
 and the mark is active, by acting on the region instead of their usual
 default part of the buffer's text.  Examples of such commands include
-\\[comment-dwim], \\[flush-lines], \\[ispell], \\[keep-lines],
-\\[query-replace], \\[query-replace-regexp], and \\[undo].  Invoke
-\\[apropos-documentation] and type \"transient\" or \"mark.*active\" at
-the prompt, to see the documentation of commands which are sensitive to
-the Transient Mark mode."
+\\[comment-dwim], \\[flush-lines], \\[keep-lines], \
+\\[query-replace], \\[query-replace-regexp], \\[ispell], and \\[undo].
+Invoke \\[apropos-documentation] and type \"transient\" or
+\"mark.*active\" at the prompt, to see the documentation of
+commands which are sensitive to the Transient Mark mode."
   :global t :group 'editing-basics :require nil)
 
+(defvar widen-automatically t
+  "Non-nil means it is ok for commands to call `widen' when they want to.
+Some commands will do this in order to go to positions outside
+the current accessible part of the buffer.
+
+If `widen-automatically' is nil, these commands will do something else
+as a fallback, and won't change the buffer bounds.")
+
 (defun pop-global-mark ()
   "Pop off global mark ring and jump to the top location."
   (interactive)
@@ -2956,7 +3232,9 @@ the Transient Mark mode."
     (set-buffer buffer)
     (or (and (>= position (point-min))
             (<= position (point-max)))
-       (widen))
+       (if widen-automatically
+           (error "Global mark position is outside accessible part of buffer")
+         (widen)))
     (goto-char position)
     (switch-to-buffer buffer)))
 \f
@@ -2966,8 +3244,9 @@ the Transient Mark mode."
   :version "21.1"
   :group 'editing-basics)
 
-(defun next-line (&optional arg)
+(defun next-line (&optional arg try-vscroll)
   "Move cursor vertically down ARG lines.
+Interactively, vscroll tall lines if `auto-window-vscroll' is enabled.
 If there is no character in the target line exactly under the current column,
 the cursor is positioned after the character in that line which spans this
 column, or at the end of the line if it is not long enough.
@@ -2986,7 +3265,7 @@ when there is no goal column.
 If you are thinking of using this in a Lisp program, consider
 using `forward-line' instead.  It is usually easier to use
 and more reliable (no dependence on goal column, etc.)."
-  (interactive "p")
+  (interactive "p\np")
   (or arg (setq arg 1))
   (if (and next-line-add-newlines (= arg 1))
       (if (save-excursion (end-of-line) (eobp))
@@ -2994,16 +3273,17 @@ and more reliable (no dependence on goal column, etc.)."
          (let ((abbrev-mode nil))
            (end-of-line)
            (insert "\n"))
-       (line-move arg))
+       (line-move arg nil nil try-vscroll))
     (if (interactive-p)
        (condition-case nil
-           (line-move arg)
+           (line-move arg nil nil try-vscroll)
          ((beginning-of-buffer end-of-buffer) (ding)))
-      (line-move arg)))
+      (line-move arg nil nil try-vscroll)))
   nil)
 
-(defun previous-line (&optional arg)
+(defun previous-line (&optional arg try-vscroll)
   "Move cursor vertically up ARG lines.
+Interactively, vscroll tall lines if `auto-window-vscroll' is enabled.
 If there is no character in the target line exactly over the current column,
 the cursor is positioned after the character in that line which spans this
 column, or at the end of the line if it is not long enough.
@@ -3018,13 +3298,13 @@ when there is no goal column.
 If you are thinking of using this in a Lisp program, consider using
 `forward-line' with a negative argument instead.  It is usually easier
 to use and more reliable (no dependence on goal column, etc.)."
-  (interactive "p")
+  (interactive "p\np")
   (or arg (setq arg 1))
   (if (interactive-p)
       (condition-case nil
-         (line-move (- arg))
+         (line-move (- arg) nil nil try-vscroll)
        ((beginning-of-buffer end-of-buffer) (ding)))
-    (line-move (- arg)))
+    (line-move (- arg) nil nil try-vscroll))
   nil)
 
 (defcustom track-eol nil
@@ -3047,13 +3327,13 @@ 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.")
 
-(defcustom line-move-ignore-invisible nil
+(defcustom line-move-ignore-invisible t
   "*Non-nil means \\[next-line] and \\[previous-line] ignore invisible lines.
 Outline mode sets this."
   :type 'boolean
   :group 'editing-basics)
 
-(defun line-move-invisible (pos)
+(defun line-move-invisible-p (pos)
   "Return non-nil if the character after POS is currently invisible."
   (let ((prop
         (get-char-property pos 'invisible)))
@@ -3062,14 +3342,55 @@ Outline mode sets this."
       (or (memq prop buffer-invisibility-spec)
          (assq prop buffer-invisibility-spec)))))
 
+;; This is like line-move-1 except that it also performs
+;; vertical scrolling of tall images if appropriate.
+;; That is not really a clean thing to do, since it mixes
+;; scrolling with cursor motion.  But so far we don't have
+;; a cleaner solution to the problem of making C-n do something
+;; useful given a tall image.
+(defun line-move (arg &optional noerror to-end try-vscroll)
+  (if (and auto-window-vscroll try-vscroll
+          ;; But don't vscroll in a keyboard macro.
+          (not defining-kbd-macro)
+          (not executing-kbd-macro))
+      (let ((forward (> arg 0))
+           (part (nth 2 (pos-visible-in-window-p (point) nil t))))
+       (if (and (consp part)
+                (> (if forward (cdr part) (car part)) 0))
+           (set-window-vscroll nil
+                               (if forward
+                                   (+ (window-vscroll nil t)
+                                      (min (cdr part)
+                                           (* (frame-char-height) arg)))
+                                 (max 0
+                                      (- (window-vscroll nil t)
+                                         (min (car part)
+                                              (* (frame-char-height) (- arg))))))
+                               t)
+         (set-window-vscroll nil 0)
+         (when (line-move-1 arg noerror to-end)
+           (when (not forward)
+             ;; Update display before calling pos-visible-in-window-p,
+             ;; because it depends on window-start being up-to-date.
+             (sit-for 0)
+             ;; If the current line is partly hidden at the bottom,
+             ;; scroll it partially up so as to unhide the bottom.
+             (if (and (setq part (nth 2 (pos-visible-in-window-p
+                                         (line-beginning-position) nil t)))
+                      (> (cdr part) 0))
+                 (set-window-vscroll nil (cdr part) t)))
+           t)))
+    (line-move-1 arg noerror to-end)))
+
 ;; This is the guts of next-line and previous-line.
 ;; Arg says how many lines to move.
-(defun line-move (arg)
+;; The value is t if we can move the specified number of lines.
+(defun line-move-1 (arg &optional noerror to-end)
   ;; Don't run any point-motion hooks, and disregard intangibility,
   ;; for intermediate positions.
   (let ((inhibit-point-motion-hooks t)
        (opoint (point))
-       new line-end line-beg)
+       (forward (> arg 0)))
     (unwind-protect
        (progn
          (if (not (memq last-command '(next-line previous-line)))
@@ -3080,6 +3401,7 @@ Outline mode sets this."
                             (or (not (bolp)) (eq last-command 'end-of-line)))
                        9999
                      (current-column))))
+
          (if (and (not (integerp selective-display))
                   (not line-move-ignore-invisible))
              ;; Use just newline characters.
@@ -3095,28 +3417,64 @@ Outline mode sets this."
                    (and (zerop (forward-line arg))
                         (bolp)
                         (setq arg 0)))
-                 (signal (if (< arg 0)
-                             'beginning-of-buffer
-                           'end-of-buffer)
-                         nil))
+                 (unless noerror
+                   (signal (if (< arg 0)
+                               'beginning-of-buffer
+                             'end-of-buffer)
+                           nil)))
            ;; Move by arg lines, but ignore invisible ones.
-           (while (> arg 0)
-             ;; If the following character is currently invisible,
-             ;; skip all characters with that same `invisible' property value.
-             (while (and (not (eobp)) (line-move-invisible (point)))
-               (goto-char (next-char-property-change (point))))
-             ;; Now move a line.
-             (end-of-line)
-             (and (zerop (vertical-motion 1))
-                  (signal 'end-of-buffer nil))
-             (setq arg (1- arg)))
-           (while (< arg 0)
-             (beginning-of-line)
-             (and (zerop (vertical-motion -1))
-                  (signal 'beginning-of-buffer nil))
-             (setq arg (1+ arg))
-             (while (and (not (bobp)) (line-move-invisible (1- (point))))
-               (goto-char (previous-char-property-change (point)))))))
+           (let (done)
+             (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)))
+                 (goto-char (next-char-property-change (point))))
+               ;; Now move a line.
+               (end-of-line)
+               ;; If there's no invisibility here, move over the newline.
+               (if (and (not (integerp selective-display))
+                        (not (line-move-invisible-p (point))))
+                   ;; We avoid vertical-motion when possible
+                   ;; because that has to fontify.
+                   (if (eobp)
+                       (if (not noerror)
+                           (signal 'end-of-buffer nil)
+                         (setq done t))
+                     (forward-line 1))
+                 ;; Otherwise move a more sophisticated way.
+                 ;; (What's the logic behind this code?)
+                 (and (zerop (vertical-motion 1))
+                      (if (not noerror)
+                          (signal 'end-of-buffer nil)
+                        (setq done t))))
+               (unless done
+                 (setq arg (1- arg))))
+             ;; The logic of this is the same as the loop above,
+             ;; it just goes in the other direction.
+             (while (and (< arg 0) (not done))
+               (beginning-of-line)
+               (if (or (bobp)
+                       (and (not (integerp selective-display))
+                            (not (line-move-invisible-p (1- (point))))))
+                   (if (bobp)
+                       (if (not noerror)
+                           (signal 'beginning-of-buffer nil)
+                         (setq done t))
+                     (forward-line -1))
+                 (if (zerop (vertical-motion -1))
+                     (if (not noerror)
+                         (signal 'beginning-of-buffer nil)
+                       (setq done t))))
+               (unless done
+                 (setq arg (1+ arg))
+                 (while (and ;; Don't move over previous invis lines
+                         ;; 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))))
+                   (goto-char (previous-char-property-change (point))))))))
+         ;; This is the value the function returns.
+         (= arg 0))
 
       (cond ((> arg 0)
             ;; If we did not move down as far as desired,
@@ -3127,10 +3485,10 @@ Outline mode sets this."
             ;; at least go to end of line.
             (beginning-of-line))
            (t
-            (line-move-finish (or goal-column temporary-goal-column) opoint)))))
-  nil)
+            (line-move-finish (or goal-column temporary-goal-column)
+                              opoint forward))))))
 
-(defun line-move-finish (column opoint)
+(defun line-move-finish (column opoint forward)
   (let ((repeat t))
     (while repeat
       ;; Set REPEAT to t to repeat the whole thing.
@@ -3140,10 +3498,13 @@ Outline mode sets this."
            (line-beg (save-excursion (beginning-of-line) (point)))
            (line-end
             ;; Compute the end of the line
-            ;; ignoring effectively intangible newlines.
-            (let ((inhibit-point-motion-hooks nil)
-                  (inhibit-field-text-motion t))
-              (save-excursion (end-of-line) (point)))))
+            ;; ignoring effectively invisible newlines.
+            (save-excursion
+              (end-of-line)
+              (while (and (not (eobp)) (line-move-invisible-p (point)))
+                (goto-char (next-char-property-change (point)))
+                (end-of-line))
+              (point))))
 
        ;; Move to the desired column.
        (line-move-to-column column)
@@ -3165,7 +3526,13 @@ Outline mode sets this."
            ;; try the previous allowable position.
            ;; See if it is ok.
            (backward-char)
-           (if (<= (point) line-end)
+           (if (if forward
+                   ;; If going forward, don't accept the previous
+                   ;; allowable position if it is before the target line.
+                   (< line-beg (point))
+                 ;; If going backward, don't accept the previous
+                 ;; allowable position if it is still after the target line.
+                 (<= (point) line-end))
                (setq new (point))
              ;; As a last resort, use the end of the line.
              (setq new line-end))))
@@ -3194,13 +3561,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 (1- (point))))
+            (not (bolp)) (line-move-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 (point)))
+                 (line-move-invisible-p (point)))
        (goto-char (next-char-property-change (point))))
       ;; Have we advanced to a larger column position?
       (if (> (current-column) normal-column)
@@ -3213,9 +3580,66 @@ 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 (1- (point))))
+         (while (and (not (bolp)) (line-move-invisible-p (1- (point))))
            (goto-char (previous-char-property-change (point) line-beg))))))))
 
+(defun move-end-of-line (arg)
+  "Move point to end of current line.
+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.
+
+This command does not move point across a field boundary unless doing so
+would move beyond there to a different line; if ARG is nil or 1, and
+point starts at a field boundary, point does not move.  To ignore field
+boundaries bind `inhibit-field-text-motion' to t."
+  (interactive "p")
+  (or arg (setq arg 1))
+  (let (done)
+    (while (not done)
+      (let ((newpos
+            (save-excursion
+              (let ((goal-column 0))
+                (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))))
+                       (backward-char 1)))
+                (point)))))
+       (goto-char newpos)
+       (if (and (> (point) newpos)
+                (eq (preceding-char) ?\n))
+           (backward-char 1)
+         (if (and (> (point) newpos) (not (eobp))
+                  (not (eq (following-char) ?\n)))
+             ;; If we skipped something intangible
+             ;; and now we're not really at eol,
+             ;; keep going.
+             (setq arg 1)
+           (setq done t)))))))
+
+(defun move-beginning-of-line (arg)
+  "Move point to beginning of current display line.
+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.
+
+This command does not move point across a field boundary unless doing so
+would move beyond there to a different line; if ARG is nil or 1, and
+point starts at a field boundary, point does not move.  To ignore field
+boundaries bind `inhibit-field-text-motion' to t."
+  (interactive "p")
+  (or arg (setq arg 1))
+  (if (/= arg 1)
+      (line-move (1- arg) t))
+  (beginning-of-line 1)
+  (let ((orig (point)))
+    (vertical-motion 0)
+    (if (/= orig (point))
+       (goto-char (constrain-to-field (point) orig (/= 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.
 (put 'set-goal-column 'disabled t)
@@ -3249,7 +3673,6 @@ For more details, see the documentation for `scroll-other-window'."
    (if (eq lines '-) nil
      (if (null lines) '-
        (- (prefix-numeric-value lines))))))
-(define-key esc-map [?\C-\S-v] 'scroll-other-window-down)
 
 (defun beginning-of-buffer-other-window (arg)
   "Move point to the beginning of the buffer in the other window.
@@ -3264,7 +3687,8 @@ With arg N, put point N/10 of the way from the true beginning."
        (progn
          (select-window window)
          ;; Set point and mark in that window's buffer.
-         (beginning-of-buffer arg)
+         (with-no-warnings
+          (beginning-of-buffer arg))
          ;; Set point accordingly.
          (recenter '(t)))
       (select-window orig-window))))
@@ -3280,7 +3704,8 @@ With arg N, put point N/10 of the way from the true end."
     (unwind-protect
        (progn
          (select-window window)
-         (end-of-buffer arg)
+         (with-no-warnings
+          (end-of-buffer arg))
          (recenter '(t)))
       (select-window orig-window))))
 \f
@@ -3405,12 +3830,19 @@ With argument, do this that many times."
   (interactive "p")
   (forward-word (- (or arg 1))))
 
-(defun mark-word (arg)
-  "Set mark arg words away from point.
-If this command is repeated, it marks the next ARG words after the ones
-already marked."
-  (interactive "p")
-  (cond ((and (eq last-command this-command) (mark t))
+(defun mark-word (&optional arg allow-extend)
+  "Set mark ARG words away from point.
+The place mark goes is the same place \\[forward-word] would
+move to with the same argument.
+Interactively, if this command is repeated
+or (in Transient Mark mode) if the mark is active,
+it marks the next ARG words after the ones already marked."
+  (interactive "P\np")
+  (cond ((and allow-extend
+             (or (and (eq last-command this-command) (mark t))
+                 (and transient-mark-mode mark-active)))
+        (setq arg (if arg (prefix-numeric-value arg)
+                    (if (< (mark) (point)) -1 1)))
         (set-mark
          (save-excursion
            (goto-char (mark))
@@ -3419,7 +3851,7 @@ already marked."
        (t
         (push-mark
          (save-excursion
-           (forward-word arg)
+           (forward-word (prefix-numeric-value arg))
            (point))
          nil t))))
 
@@ -3591,6 +4023,7 @@ Setting this variable automatically makes it local to the current buffer.")
   "The function to use for `auto-fill-function' if Auto Fill mode is turned on.
 Some major modes set this.")
 
+(put 'auto-fill-function :minor-mode-function 'auto-fill-mode)
 ;; FIXME: turn into a proper minor mode.
 ;; Add a global minor mode version of it.
 (defun auto-fill-mode (&optional arg)
@@ -3809,16 +4242,13 @@ when it is off screen)."
                   (setq blinkpos (scan-sexps oldpos -1)))
               (error nil)))
           (and blinkpos
-               (save-excursion
-                 (goto-char blinkpos)
-                 (not (looking-at "\\s$")))
+                ;; Not syntax '$'.
+               (not (eq (syntax-class (syntax-after blinkpos)) 8))
                (setq matching-paren
-                     (or (and parse-sexp-lookup-properties
-                              (let ((prop (get-text-property blinkpos 'syntax-table)))
-                                (and (consp prop)
-                                     (eq (car prop) 4)
-                                     (cdr prop))))
-                         (matching-paren (char-after blinkpos)))
+                     (let ((syntax (syntax-after blinkpos)))
+                       (and (consp syntax)
+                            (eq (syntax-class syntax) 4)
+                            (cdr syntax)))
                      mismatch
                      (or (null matching-paren)
                          (/= (char-after (1- oldpos))
@@ -3882,11 +4312,11 @@ During execution of Lisp code, this character causes a quit directly.
 At top-level, as an editor command, this simply beeps."
   (interactive)
   (deactivate-mark)
+  (if (fboundp 'kmacro-keyboard-quit)
+      (kmacro-keyboard-quit))
   (setq defining-kbd-macro nil)
   (signal 'quit nil))
 
-(define-key global-map "\C-g" 'keyboard-quit)
-
 (defvar buffer-quit-function nil
   "Function to call to \"quit\" the current buffer, or nil if none.
 \\[keyboard-escape-quit] calls this function when its more local actions
@@ -3905,8 +4335,7 @@ or go back to just one window (by deleting all but the selected window)."
         (abort-recursive-edit))
        (current-prefix-arg
         nil)
-       ((and transient-mark-mode
-             mark-active)
+       ((and transient-mark-mode mark-active)
         (deactivate-mark))
        ((> (recursion-depth) 0)
         (exit-recursive-edit))
@@ -3930,8 +4359,7 @@ specification for `play-sound'."
     (push 'sound sound)
     (play-sound sound)))
 
-(define-key global-map "\e\e\e" 'keyboard-escape-quit)
-
+\f
 (defcustom read-mail-command 'rmail
   "*Your preference for a mail reading package.
 This is used by some keybindings which support reading mail.
@@ -4073,7 +4501,7 @@ Each action has the form (FUNCTION . ARGS)."
    (list nil nil nil current-prefix-arg))
   (compose-mail to subject other-headers continue
                'switch-to-buffer-other-frame yank-action send-actions))
-
+\f
 (defvar set-variable-value-history nil
   "History of values entered with `set-variable'.")
 
@@ -4136,7 +4564,7 @@ With a prefix argument, set VARIABLE to VALUE buffer-locally."
   ;; Force a thorough redisplay for the case that the variable
   ;; has an effect on the display, like `tab-width' has.
   (force-mode-line-update))
-
+\f
 ;; Define the major mode for lists of completions.
 
 (defvar completion-list-mode-map nil
@@ -4144,6 +4572,7 @@ With a prefix argument, set VARIABLE to VALUE buffer-locally."
 (or completion-list-mode-map
     (let ((map (make-sparse-keymap)))
       (define-key map [mouse-2] 'mouse-choose-completion)
+      (define-key map [follow-link] 'mouse-face)
       (define-key map [down-mouse-2] nil)
       (define-key map "\C-m" 'choose-completion)
       (define-key map "\e\e\e" 'delete-completion-window)
@@ -4342,7 +4771,7 @@ Use \\<completion-list-mode-map>\\[mouse-choose-completion] to select one\
   (setq major-mode 'completion-list-mode)
   (make-local-variable 'completion-base-size)
   (setq completion-base-size nil)
-  (run-hooks 'completion-list-mode-hook))
+  (run-mode-hooks 'completion-list-mode-hook))
 
 (defun completion-list-mode-finish ()
   "Finish setup of the completions buffer.
@@ -4411,7 +4840,11 @@ of the differing parts is, by contrast, slightly highlighted."
                    (- (point) (minibuffer-prompt-end)))))
        ;; Otherwise, in minibuffer, the whole input is being completed.
        (if (minibufferp mainbuf)
-           (setq completion-base-size 0)))
+           (if (and (symbolp minibuffer-completion-table)
+                    (get minibuffer-completion-table 'completion-base-size-function))
+               (setq completion-base-size 
+                     (funcall (get minibuffer-completion-table 'completion-base-size-function)))
+             (setq completion-base-size 0))))
       ;; Put faces on first uncommon characters and common parts.
       (when completion-base-size
        (let* ((common-string-length
@@ -4420,7 +4853,8 @@ of the differing parts is, by contrast, slightly highlighted."
                               (point-min)
                               'mouse-face))
               (element-common-end
-               (+ (or element-start nil) common-string-length))
+               (and element-start
+                    (+ (or element-start nil) common-string-length)))
               (maxp (point-max)))
          (while (and element-start (< element-common-end maxp))
            (when (and (get-char-property element-start 'mouse-face)
@@ -4721,11 +5155,21 @@ the front of the list of recently selected ones."
     (set-buffer buffer)
     (clone-indirect-buffer nil t norecord)))
 
-(define-key ctl-x-4-map "c" 'clone-indirect-buffer-other-window)
 \f
 ;;; Handling of Backspace and Delete keys.
 
-(defcustom normal-erase-is-backspace nil
+(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
@@ -4834,14 +5278,6 @@ See also `normal-erase-is-backspace'."
       (message "Delete key deletes %s"
               (if normal-erase-is-backspace "forward" "backward"))))
 \f
-(defcustom idle-update-delay 0.5
-  "*Idle time delay before updating various things on the screen.
-Various Emacs features that update auxiliary information when point moves
-wait this many seconds after Emacs becomes idle before doing an update."
-  :type 'number
-  :group 'display
-  :version "21.4")
-\f
 (defvar vis-mode-saved-buffer-invisibility-spec nil
   "Saved value of `buffer-invisibility-spec' when Visible mode is on.")
 
@@ -4853,6 +5289,7 @@ Enabling Visible mode makes all invisible text temporarily visible.
 Disabling Visible mode turns off that effect.  Visible mode
 works by saving the value of `buffer-invisibility-spec' and setting it to nil."
   :lighter " Vis"
+  :group 'editing-basics
   (when (local-variable-p 'vis-mode-saved-buffer-invisibility-spec)
     (setq buffer-invisibility-spec vis-mode-saved-buffer-invisibility-spec)
     (kill-local-variable 'vis-mode-saved-buffer-invisibility-spec))