Add arch taglines
[bpt/emacs.git] / lisp / simple.el
index 416b693..46bfc12 100644 (file)
@@ -1,6 +1,7 @@
 ;;; simple.el --- basic editing commands for Emacs
 
-;; Copyright (C) 1985, 86, 87, 93, 94, 95, 96, 97, 98, 99, 2000, 2001, 2002
+;; Copyright (C) 1985, 86, 87, 93, 94, 95, 96, 97, 98, 99,
+;;               2000, 2001, 2002, 2003
 ;;        Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
@@ -79,7 +80,7 @@ If `use-hard-newlines' is non-nil, the newline is marked with the
 text-property `hard'.
 With ARG, insert that many newlines.
 Call `auto-fill-function' if the current column number is greater
-than the value of `fill-column' and ARG is `nil'."
+than the value of `fill-column' and ARG is nil."
   (interactive "*P")
   (barf-if-buffer-read-only)
   ;; Inserting a newline at the end of a line produces better redisplay in
@@ -180,13 +181,27 @@ With arg N, insert N newlines."
     (goto-char loc)
     (end-of-line)))
 
-(defun split-line ()
-  "Split current line, moving portion beyond point vertically down."
-  (interactive "*")
+(defun split-line (&optional arg)
+  "Split current line, moving portion beyond point vertically down.
+If the current line starts with `fill-prefix', insert it on the new
+line as well.  With prefix arg, don't insert fill-prefix on new line.
+
+When called from Lisp code, the arg may be a prefix string to copy."
+  (interactive "*P")
   (skip-chars-forward " \t")
-  (let ((col (current-column))
-       (pos (point)))
+  (let* ((col (current-column))
+        (pos (point))
+        ;; What prefix should we check for (nil means don't).
+        (prefix (cond ((stringp arg) arg)
+                      (arg nil)
+                      (t fill-prefix)))
+        ;; Does this line start with it?
+        (have-prfx (and prefix
+                        (save-excursion
+                          (beginning-of-line)
+                          (looking-at (regexp-quote prefix))))))
     (newline 1)
+    (if have-prfx (insert-and-inherit prefix))
     (indent-to col 0)
     (goto-char pos)))
 
@@ -318,10 +333,11 @@ In binary overwrite mode, this function does overwrite, and octal
 digits are interpreted as a character code.  This is intended to be
 useful for editing binary files."
   (interactive "*p")
-  (let ((char (if (or (not overwrite-mode)
-                     (eq overwrite-mode 'overwrite-mode-binary))
-                 (read-quoted-char)
-               (read-char))))
+  (let* ((char (let (translation-table-for-input)
+                (if (or (not overwrite-mode)
+                        (eq overwrite-mode 'overwrite-mode-binary))
+                    (read-quoted-char)
+                  (read-char)))))
     ;; Assume character codes 0240 - 0377 stand for characters in some
     ;; single-byte character set, and convert them to Emacs
     ;; characters.
@@ -336,23 +352,25 @@ useful for editing binary files."
       (insert-and-inherit char)
       (setq arg (1- arg)))))
 
-(defun forward-to-indentation (arg)
+(defun forward-to-indentation (&optional arg)
   "Move forward ARG lines and position at first nonblank character."
   (interactive "p")
-  (forward-line arg)
+  (forward-line (or arg 1))
   (skip-chars-forward " \t"))
 
-(defun backward-to-indentation (arg)
+(defun backward-to-indentation (&optional arg)
   "Move backward ARG lines and position at first nonblank character."
   (interactive "p")
-  (forward-line (- arg))
+  (forward-line (- (or arg 1)))
   (skip-chars-forward " \t"))
 
 (defun back-to-indentation ()
   "Move point to the first non-whitespace character on this line."
   (interactive)
   (beginning-of-line 1)
-  (skip-chars-forward " \t"))
+  (skip-syntax-forward " " (line-end-position))
+  ;; Move back over chars that have whitespace syntax but have the p flag.
+  (backward-prefix-chars))
 
 (defun fixup-whitespace ()
   "Fixup white space between objects around point.
@@ -489,11 +507,11 @@ that uses or sets the mark."
        (setq start (point))
        (goto-char opoint)
        (forward-line 0)
-       (if (/= start 1)
+       (if (/= start (point-min))
            (message "line %d (narrowed line %d)"
-                    (1+ (count-lines 1 (point)))
+                    (1+ (count-lines (point-min) (point)))
                     (1+ (count-lines start (point))))
-         (message "Line %d" (1+ (count-lines 1 (point)))))))))
+         (message "Line %d" (1+ (count-lines (point-min) (point)))))))))
 
 (defun count-lines (start end)
   "Return number of lines between START and END.
@@ -643,21 +661,25 @@ the echo area."
 
   (let ((print-length eval-expression-print-length)
        (print-level eval-expression-print-level))
-    (prin1 (car values)
-          (if eval-expression-insert-value (current-buffer) t))))
+    (if eval-expression-insert-value
+       (with-no-warnings
+        (eval-last-sexp-print-value (car values)))
+      (prin1 (car values) t))))
 
 (defun edit-and-eval-command (prompt command)
   "Prompting with PROMPT, let user edit COMMAND and eval result.
 COMMAND is a Lisp expression.  Let user edit that expression in
 the minibuffer, then read and evaluate the result."
-  (let ((command (read-from-minibuffer prompt
-                                      (prin1-to-string command)
-                                      read-expression-map t
-                                      '(command-history . 1))))
-    ;; If command was added to command-history as a string,
-    ;; get rid of that.  We want only evaluable expressions there.
-    (if (stringp (car command-history))
-       (setq command-history (cdr command-history)))
+  (let ((command
+        (unwind-protect
+            (read-from-minibuffer prompt
+                                  (prin1-to-string command)
+                                  read-expression-map t
+                                  '(command-history . 1))
+          ;; If command was added to command-history as a string,
+          ;; get rid of that.  We want only evaluable expressions there.
+          (if (stringp (car command-history))
+              (setq command-history (cdr command-history))))))
 
     ;; If command to be redone does not match front of history,
     ;; add it to the history.
@@ -683,21 +705,25 @@ to get different commands to edit and resubmit."
                (let ((print-level nil)
                      (minibuffer-history-position arg)
                      (minibuffer-history-sexp-flag (1+ (minibuffer-depth))))
-                 (read-from-minibuffer
-                  "Redo: " (prin1-to-string elt) read-expression-map t
-                  (cons 'command-history arg))))
+                 (unwind-protect
+                     (read-from-minibuffer
+                      "Redo: " (prin1-to-string elt) read-expression-map t
+                      (cons 'command-history arg))
 
-         ;; If command was added to command-history as a string,
-         ;; get rid of that.  We want only evaluable expressions there.
-         (if (stringp (car command-history))
-             (setq command-history (cdr command-history)))
+                   ;; If command was added to command-history as a
+                   ;; string, get rid of that.  We want only
+                   ;; evaluable expressions there.
+                   (if (stringp (car command-history))
+                       (setq command-history (cdr command-history))))))
 
          ;; If command to be redone does not match front of history,
          ;; add it to the history.
          (or (equal newcmd (car command-history))
              (setq command-history (cons newcmd command-history)))
          (eval newcmd))
-      (ding))))
+      (if command-history
+         (error "Argument %d is beyond length of command history" arg)
+       (error "There are no previous complex commands to repeat")))))
 \f
 (defvar minibuffer-history nil
   "Default minibuffer history list.
@@ -913,13 +939,22 @@ Return 0 if current buffer is not a mini-buffer."
 ;Put this on C-x u, so we can force that rather than C-_ into startup msg
 (defalias 'advertised-undo 'undo)
 
+(defconst undo-equiv-table (make-hash-table :test 'eq :weakness t)
+  "Table mapping redo records to the corresponding undo one.")
+
+(defvar undo-in-region nil
+  "Non-nil if `pending-undo-list' is not just a tail of `buffer-undo-list'.")
+
+(defvar undo-no-redo nil
+  "If t, `undo' doesn't go through redo entries.")
+
 (defun undo (&optional arg)
   "Undo some previous changes.
 Repeat this command to undo more changes.
 A numeric argument serves as a repeat count.
 
 In Transient Mark mode when the mark is active, only undo changes within
-the current region.  Similarly, when not in Transient Mark mode, just C-u
+the current region.  Similarly, when not in Transient Mark mode, just \\[universal-argument]
 as an argument limits undo to changes within the current region."
   (interactive "*P")
   ;; Make last-command indicate for the next command that this was an undo.
@@ -931,18 +966,36 @@ as an argument limits undo to changes within the current region."
   (setq this-command 'undo)
   (let ((modified (buffer-modified-p))
        (recent-save (recent-auto-save-p)))
-    (or (eq (selected-window) (minibuffer-window))
-       (message "Undo!"))
     (unless (eq last-command 'undo)
-      (if (if transient-mark-mode mark-active (and arg (not (numberp arg))))
+      (setq undo-in-region
+           (if transient-mark-mode mark-active (and arg (not (numberp arg)))))
+      (if undo-in-region
          (undo-start (region-beginning) (region-end))
        (undo-start))
       ;; get rid of initial undo boundary
       (undo-more 1))
+    ;; Check to see whether we're hitting a redo record, and if
+    ;; so, ask the user whether she wants to skip the redo/undo pair.
+    (let ((equiv (gethash pending-undo-list undo-equiv-table)))
+      (or (eq (selected-window) (minibuffer-window))
+         (message (if undo-in-region
+                      (if equiv "Redo in region!" "Undo in region!")
+                    (if equiv "Redo!" "Undo!"))))
+      (when (and 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)))
+                (if next (setq equiv next))))
+       (setq pending-undo-list equiv)))
     (undo-more
      (if (or transient-mark-mode (numberp arg))
         (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.
+    ;; 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))
     ;; 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)
@@ -950,9 +1003,9 @@ as an argument limits undo to changes within the current region."
       (while (car tail)
        (when (integerp (car tail))
          (let ((pos (car tail)))
-           (if (null prev)
-               (setq buffer-undo-list (cdr tail))
-             (setcdr prev (cdr tail)))
+           (if prev
+               (setcdr prev (cdr tail))
+             (setq buffer-undo-list (cdr tail)))
            (setq tail (cdr tail))
            (while (car tail)
              (if (eq pos (car tail))
@@ -967,6 +1020,17 @@ as an argument limits undo to changes within the current region."
     (and modified (not (buffer-modified-p))
         (delete-auto-save-file-if-necessary recent-save))))
 
+(defun undo-only (&optional arg)
+  "Undo some previous changes.
+Repeat this command to undo more changes.
+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.")
 
@@ -979,7 +1043,9 @@ Some change-hooks test this variable to do something different.")
 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
-      (error "No further undo information"))
+      (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))))
 
@@ -1085,7 +1151,7 @@ we stop and ignore all further elements."
 If it crosses the edge, we return nil."
   (cond ((integerp undo-elt)
         (and (>= undo-elt start)
-             (<  undo-elt end)))
+             (<= undo-elt end)))
        ((eq undo-elt nil)
         t)
        ((atom undo-elt)
@@ -1105,16 +1171,16 @@ If it crosses the edge, we return nil."
                   (cons alist-elt undo-adjusted-markers)))
           (and (cdr alist-elt)
                (>= (cdr alist-elt) start)
-               (< (cdr alist-elt) end))))
+               (<= (cdr alist-elt) end))))
        ((null (car undo-elt))
         ;; (nil PROPERTY VALUE BEG . END)
         (let ((tail (nthcdr 3 undo-elt)))
           (and (>= (car tail) start)
-               (< (cdr tail) end))))
+               (<= (cdr tail) end))))
        ((integerp (car undo-elt))
         ;; (BEGIN . END)
         (and (>= (car undo-elt) start)
-             (< (cdr undo-elt) end)))))
+             (<= (cdr undo-elt) end)))))
 
 (defun undo-elt-crosses-region (undo-elt start end)
   "Test whether UNDO-ELT crosses one edge of that region START ... END.
@@ -1154,7 +1220,7 @@ is not *inside* the region START...END."
 
 (defvar shell-command-default-error-buffer nil
   "*Buffer name for `shell-command' and `shell-command-on-region' error output.
-This buffer is used when `shell-command' or 'shell-command-on-region'
+This buffer is used when `shell-command' or `shell-command-on-region'
 is run interactively.  A value of nil means that output to stderr and
 stdout will be intermixed in the output stream.")
 
@@ -1278,8 +1344,7 @@ specifies the value of ERROR-BUFFER."
                    (if (yes-or-no-p "A command is running.  Kill it? ")
                        (kill-process proc)
                      (error "Shell command in progress")))
-               (save-excursion
-                 (set-buffer buffer)
+               (with-current-buffer buffer
                  (setq buffer-read-only nil)
                  (erase-buffer)
                  (display-buffer buffer)
@@ -1335,7 +1400,8 @@ and only used if a buffer is displayed."
                  (if (= (buffer-size) 0)
                      0
                    (count-lines (point-min) (point-max)))))
-            (cond ((and (or (<= lines 1)
+            (cond ((= lines 0))
+                  ((and (or (<= lines 1)
                             (<= lines
                                 (if resize-mini-windows
                                     (cond ((floatp max-mini-window-height)
@@ -1500,7 +1566,7 @@ specifies the value of ERROR-BUFFER."
                                         nil shell-command-switch command)))
          ;; Report the output.
          (with-current-buffer buffer
-           (setq mode-line-process 
+           (setq mode-line-process
                  (cond ((null exit-status)
                         " - Error")
                        ((stringp exit-status)
@@ -1729,14 +1795,30 @@ ring directly.")
 (defvar kill-ring-yank-pointer nil
   "The tail of the kill ring whose car is the last thing yanked.")
 
-(defun kill-new (string &optional replace)
+(defun kill-new (string &optional replace yank-handler)
   "Make STRING the latest kill in the kill ring.
 Set `kill-ring-yank-pointer' to point to it.
 If `interprogram-cut-function' is non-nil, apply it to STRING.
 Optional second argument REPLACE non-nil means that STRING will replace
-the front of the kill ring, rather than being added to the list."
-  (and (fboundp 'menu-bar-update-yank-menu)
-       (menu-bar-update-yank-menu string (and replace (car kill-ring))))
+the front of the kill ring, rather than being added to the list.
+
+Optional third arguments YANK-HANDLER controls how the STRING is later
+inserted into a buffer; see `insert-for-yank' for details.
+When a yank handler is specified, STRING must be non-empty (the yank
+handler is stored as a `yank-handler'text property on STRING).
+
+When the yank handler has a non-nil PARAM element, the original STRING
+argument is not used by `insert-for-yank'.  However, since Lisp code
+may access and use elements from the kill-ring directly, the STRING
+argument should still be a \"useful\" string for such uses."
+  (if (> (length string) 0)
+      (if yank-handler
+         (put-text-property 0 1 'yank-handler yank-handler string))
+    (if yank-handler
+       (signal 'args-out-of-range
+               (list string "yank-handler specified for empty string"))))
+  (if (fboundp 'menu-bar-update-yank-menu)
+      (menu-bar-update-yank-menu string (and replace (car kill-ring))))
   (if (and replace kill-ring)
       (setcar kill-ring string)
     (setq kill-ring (cons string kill-ring))
@@ -1746,15 +1828,20 @@ the front of the kill ring, rather than being added to the list."
   (if interprogram-cut-function
       (funcall interprogram-cut-function string (not replace))))
 
-(defun kill-append (string before-p)
+(defun kill-append (string before-p &optional yank-handler)
   "Append STRING to the end of the latest kill in the kill ring.
 If BEFORE-P is non-nil, prepend STRING to the kill.
-If `interprogram-cut-function' is set, pass the resulting kill to
-it."
-  (kill-new (if before-p
-               (concat string (car kill-ring))
-             (concat (car kill-ring) string))
-           t))
+Optional third argument YANK-HANDLER specifies the yank-handler text
+property to be set on the combined kill ring string.  If the specified
+yank-handler arg differs from the yank-handler property of the latest
+kill string, STRING is added as a new kill ring element instead of
+being appending to the last kill.
+If `interprogram-cut-function' is set, pass the resulting kill to it."
+  (let* ((cur (car kill-ring)))
+    (kill-new (if before-p (concat string cur) (concat cur string))
+             (or (= (length cur) 0)
+                 (equal yank-handler (get-text-property 0 'yank-handler cur)))
+             yank-handler)))
 
 (defun current-kill (n &optional do-not-move)
   "Rotate the yanking point by N places, and then return that kill.
@@ -1796,7 +1883,7 @@ yanking point; just return the Nth kill forward."
      '(text-read-only buffer-read-only error))
 (put 'text-read-only 'error-message "Text is read-only")
 
-(defun kill-region (beg end)
+(defun kill-region (beg end &optional yank-handler)
   "Kill between point and mark.
 The text is deleted but saved in the kill ring.
 The command \\[yank] can retrieve it from there.
@@ -1815,16 +1902,20 @@ Supply two arguments, character numbers indicating the stretch of text
 Any command that calls this function is a \"kill command\".
 If the previous command was also a kill command,
 the text killed this time appends to the text killed last time
-to make one entry in the kill ring."
+to make one entry in the kill ring.
+
+In Lisp code, optional third arg YANK-HANDLER 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)))
        (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)
-             (kill-append string (< end beg))
-           (kill-new string)))
-       (setq this-command 'kill-region))
+             (kill-append string (< end beg) yank-handler)
+           (kill-new string nil yank-handler)))
+       (when (or string (eq last-command 'kill-region))
+         (setq this-command 'kill-region)))
     ((buffer-read-only text-read-only)
      ;; The code above failed because the buffer, or some of the characters
      ;; in the region, are read-only.
@@ -1914,12 +2005,22 @@ 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)
-  "*Text properties to discard when yanking."
+  '(read-only invisible intangible field mouse-face help-echo local-map keymap
+    yank-handler)
+  "*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 'editing
   :version "21.4")
 
+(defvar yank-window-start nil)
+(defvar yank-undo-function nil
+  "If non-nil, function used by `yank-pop' to delete last stretch of yanked text.
+Function is called with two parameters, START and END corresponding to
+the value of the mark and point; it is guaranteed that START <= END.
+Normally set from the UNDO element of a yank-handler; see `insert-for-yank'.")
+
 (defun yank-pop (arg)
   "Replace just-yanked stretch of killed text with a different stretch.
 This command is allowed only immediately after a `yank' or a `yank-pop'.
@@ -1939,9 +2040,15 @@ comes the newest one."
   (setq this-command 'yank)
   (let ((inhibit-read-only t)
        (before (< (point) (mark t))))
-    (delete-region (point) (mark t))
+    (if before
+       (funcall (or yank-undo-function 'delete-region) (point) (mark t))
+      (funcall (or yank-undo-function 'delete-region) (mark t) (point)))
+    (setq yank-undo-function nil)
     (set-marker (mark-marker) (point) (current-buffer))
     (insert-for-yank (current-kill arg))
+    ;; Set the window start back where it was in the yank command,
+    ;; if possible.
+    (set-window-start (selected-window) yank-window-start t)
     (if before
        ;; This is like exchange-point-and-mark, but doesn't activate the mark.
        ;; It is cleaner to avoid activation, even though the command
@@ -1954,11 +2061,12 @@ comes the newest one."
   "Reinsert the last stretch of killed text.
 More precisely, reinsert the stretch of killed text most recently
 killed OR yanked.  Put point at end, and set mark at beginning.
-With just C-u as argument, same but put point at beginning (and mark at end).
+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.
 See also the command \\[yank-pop]."
   (interactive "*P")
+  (setq yank-window-start (window-start))
   ;; If we don't get all the way thru, make last-command indicate that
   ;; for the following command.
   (setq this-command t)
@@ -1974,7 +2082,8 @@ See also the command \\[yank-pop]."
       (goto-char (prog1 (mark t)
                   (set-marker (mark-marker) (point) (current-buffer)))))
   ;; If we do get all the way thru, make this-command indicate that.
-  (setq this-command 'yank)
+  (if (eq this-command t)
+      (setq this-command 'yank))
   nil)
 
 (defun rotate-yank-pointer (arg)
@@ -2022,7 +2131,7 @@ and KILLP is t if a prefix arg was specified."
              (let ((col (current-column)))
                (forward-char -1)
                (setq col (- col (current-column)))
-               (insert-char ?\ col)
+               (insert-char ?\  col)
                (delete-char 1)))
          (forward-char -1)
          (setq count (1- count))))))
@@ -2076,7 +2185,9 @@ use \\[append-next-kill] before \\[kill-line].
 
 If the buffer is read-only, Emacs will beep and refrain from deleting
 the line, but put the line in the kill ring anyway.  This means that
-you can use this command to copy text from a read-only buffer."
+you can use this command to copy text from a read-only buffer.
+\(If the variable `kill-read-only-ok' is non-nil, then this won't
+even beep.)"
   (interactive "P")
   (kill-region (point)
               ;; It is better to move point to the other end of the kill
@@ -2089,44 +2200,112 @@ you can use this command to copy text from a read-only buffer."
                     (forward-visible-line (prefix-numeric-value arg))
                   (if (eobp)
                       (signal 'end-of-buffer nil))
-                  (if (or (looking-at "[ \t]*$") (and kill-whole-line (bolp)))
-                      (forward-visible-line 1)
-                    (end-of-visible-line)))
+                  (let ((end
+                         (save-excursion
+                           (end-of-visible-line) (point))))
+                    (if (or (save-excursion
+                              (skip-chars-forward " \t" end)
+                              (= (point) end))
+                            (and kill-whole-line (bolp)))
+                        (forward-visible-line 1)
+                      (goto-char end))))
                 (point))))
 
+(defun kill-whole-line (&optional arg)
+  "Kill current line.
+With prefix arg, kill that many lines starting from the current line.
+If arg is negative, kill backward.  Also kill the preceding newline.
+\(This is meant to make C-x z work well with negative arguments.\)
+If arg is zero, kill current line but exclude the trailing newline."
+  (interactive "P")
+  (setq arg (prefix-numeric-value arg))
+  (if (and (> arg 0) (eobp) (save-excursion (forward-visible-line 0) (eobp)))
+      (signal 'end-of-buffer nil))
+  (if (and (< arg 0) (bobp) (save-excursion (end-of-visible-line) (bobp)))
+      (signal 'beginning-of-buffer nil))
+  (unless (eq last-command 'kill-region)
+    (kill-new "")
+    (setq last-command 'kill-region))
+  (cond ((zerop arg)
+        ;; We need to kill in two steps, because the previous command
+        ;; could have been a kill command, in which case the text
+        ;; before point needs to be prepended to the current kill
+        ;; ring entry and the text after point appended.  Also, we
+        ;; need to use save-excursion to avoid copying the same text
+        ;; twice to the kill ring in read-only buffers.
+        (save-excursion
+          (kill-region (point) (progn (forward-visible-line 0) (point))))
+        (kill-region (point) (progn (end-of-visible-line) (point))))
+       ((< arg 0)
+        (save-excursion
+          (kill-region (point) (progn (end-of-visible-line) (point))))
+        (kill-region (point)
+                     (progn (forward-visible-line (1+ arg))
+                            (unless (bobp) (backward-char))
+                            (point))))
+       (t
+        (save-excursion
+          (kill-region (point) (progn (forward-visible-line 0) (point))))
+        (kill-region (point)
+                     (progn (forward-visible-line arg) (point))))))
+
 (defun forward-visible-line (arg)
   "Move forward by ARG lines, ignoring currently invisible newlines only.
 If ARG is negative, move backward -ARG lines.
 If ARG is zero, move to the beginning of the current line."
   (condition-case nil
       (if (> arg 0)
-         (while (> arg 0)
-           (or (zerop (forward-line 1))
-               (signal 'end-of-buffer nil))
-           ;; If the following character is currently invisible,
-           ;; skip all characters with that same `invisible' property value,
-           ;; then find the next newline.
-           (while (and (not (eobp))
-                       (let ((prop
-                              (get-char-property (point) 'invisible)))
-                         (if (eq buffer-invisibility-spec t)
-                             prop
-                           (or (memq prop buffer-invisibility-spec)
-                               (assq prop buffer-invisibility-spec)))))
-             (goto-char
-              (if (get-text-property (point) 'invisible)
-                  (or (next-single-property-change (point) 'invisible)
-                      (point-max))
-                (next-overlay-change (point))))
+         (progn
+           (while (> arg 0)
              (or (zerop (forward-line 1))
-                 (signal 'end-of-buffer nil)))
-           (setq arg (1- arg)))
+                 (signal 'end-of-buffer nil))
+             ;; If the newline we just skipped is invisible,
+             ;; don't count it.
+             (let ((prop
+                    (get-char-property (1- (point)) 'invisible)))
+               (if (if (eq buffer-invisibility-spec t)
+                       prop
+                     (or (memq prop buffer-invisibility-spec)
+                         (assq prop buffer-invisibility-spec)))
+                   (setq arg (1+ arg))))
+             (setq arg (1- arg)))
+           ;; If invisible text follows, and it is a number of complete lines,
+           ;; skip it.
+           (let ((opoint (point)))
+             (while (and (not (eobp))
+                         (let ((prop
+                                (get-char-property (point) 'invisible)))
+                           (if (eq buffer-invisibility-spec t)
+                               prop
+                             (or (memq prop buffer-invisibility-spec)
+                                 (assq prop buffer-invisibility-spec)))))
+               (goto-char
+                (if (get-text-property (point) 'invisible)
+                    (or (next-single-property-change (point) 'invisible)
+                        (point-max))
+                  (next-overlay-change (point)))))
+             (unless (bolp)
+               (goto-char opoint))))
        (let ((first t))
-         (while (or first (< arg 0))
-           (if (zerop arg)
+         (while (or first (<= arg 0))
+           (if first
                (beginning-of-line)
              (or (zerop (forward-line -1))
                  (signal 'beginning-of-buffer nil)))
+           ;; If the newline we just moved to is invisible,
+           ;; don't count it.
+           (unless (bobp)
+             (let ((prop
+                    (get-char-property (1- (point)) 'invisible)))
+               (unless (if (eq buffer-invisibility-spec t)
+                           prop
+                         (or (memq prop buffer-invisibility-spec)
+                             (assq prop buffer-invisibility-spec)))
+                 (setq arg (1+ arg)))))
+           (setq first nil))
+         ;; If invisible text follows, and it is a number of complete lines,
+         ;; skip it.
+         (let ((opoint (point)))
            (while (and (not (bobp))
                        (let ((prop
                               (get-char-property (1- (point)) 'invisible)))
@@ -2138,11 +2317,9 @@ If ARG is zero, move to the beginning of the current line."
               (if (get-text-property (1- (point)) 'invisible)
                   (or (previous-single-property-change (point) 'invisible)
                       (point-min))
-                (previous-overlay-change (point))))
-             (or (zerop (forward-line -1))
-                 (signal 'beginning-of-buffer nil)))
-           (setq first nil)
-           (setq arg (1+ arg)))))
+                (previous-overlay-change (point)))))
+           (unless (bolp)
+             (goto-char opoint)))))
     ((beginning-of-buffer end-of-buffer)
      nil)))
 
@@ -2153,12 +2330,15 @@ If ARG is zero, move to the beginning of the current line."
   ;; skip all characters with that same `invisible' property value,
   ;; then find the next newline.
   (while (and (not (eobp))
-             (let ((prop
-                    (get-char-property (point) 'invisible)))
-               (if (eq buffer-invisibility-spec t)
-                   prop
-                 (or (memq prop buffer-invisibility-spec)
-                     (assq prop buffer-invisibility-spec)))))
+             (save-excursion
+               (skip-chars-forward "^\n")
+               (let ((prop
+                      (get-char-property (point) 'invisible)))
+                 (if (eq buffer-invisibility-spec t)
+                     prop
+                   (or (memq prop buffer-invisibility-spec)
+                       (assq prop buffer-invisibility-spec))))))
+    (skip-chars-forward "^\n")
     (if (get-text-property (point) 'invisible)
        (goto-char (next-single-property-change (point) 'invisible))
       (goto-char (next-overlay-change (point))))
@@ -2170,7 +2350,7 @@ Puts mark after the inserted text.
 BUFFER may be a buffer or a buffer name.
 
 This function is meant for the user to run interactively.
-Don't call it from programs!"
+Don't call it from programs: use `insert-buffer-substring' instead!"
   (interactive
    (list
     (progn
@@ -2180,16 +2360,10 @@ Don't call it from programs!"
                       (other-buffer (current-buffer))
                     (window-buffer (next-window (selected-window))))
                   t))))
-  (or (bufferp buffer)
-      (setq buffer (get-buffer buffer)))
-  (let (start end newmark)
-    (save-excursion
-      (save-excursion
-       (set-buffer buffer)
-       (setq start (point-min) end (point-max)))
-      (insert-buffer-substring buffer start end)
-      (setq newmark (point)))
-    (push-mark newmark))
+  (push-mark
+   (save-excursion
+     (insert-buffer-substring (get-buffer buffer))
+     (point)))
   nil)
 
 (defun append-to-buffer (buffer start end)
@@ -2345,13 +2519,23 @@ Display `Mark set' unless the optional second arg NOMSG is non-nil."
 
 (defun set-mark-command (arg)
   "Set mark at where point is, or jump to mark.
-With no prefix argument, set mark, push old mark position on local mark
-ring, and push mark on global mark ring.  Immediately repeating the
-command activates `transient-mark-mode' temporarily.
+With no prefix argument, set mark, and push old mark position on local
+mark ring; also push mark on global mark ring if last mark was set in
+another buffer.  Immediately repeating the command activates
+`transient-mark-mode' temporarily.
 
-With argument, jump to mark, and pop a new position for mark off the ring
-\(does not affect global mark ring\).  Repeating the command without
-an argument jumps to the next position off the mark ring.
+With argument, e.g. \\[universal-argument] \\[set-mark-command], \
+jump to mark, and pop a new position
+for mark off the local mark ring \(this does not affect the global
+mark ring\).  Use \\[pop-global-mark] to jump to a mark off the global
+mark ring \(see `pop-global-mark'\).
+
+Repeating the \\[set-mark-command] command without the prefix jumps to
+the next position off the local (or global) mark ring.
+
+With a double \\[universal-argument] prefix argument, e.g. \\[universal-argument] \
+\\[universal-argument] \\[set-mark-command], unconditionally
+set mark where point is.
 
 Novice Emacs Lisp programmers often try to use the mark for the wrong
 purposes.  See the documentation of `set-mark' for more information."
@@ -2359,15 +2543,18 @@ purposes.  See the documentation of `set-mark' for more information."
   (if (eq transient-mark-mode 'lambda)
       (setq transient-mark-mode nil))
   (cond
+   ((and (consp arg) (> (prefix-numeric-value arg) 4))
+    (push-mark-command nil))
    ((not (eq this-command 'set-mark-command))
     (if arg
        (pop-to-mark-command)
       (push-mark-command t)))
    ((eq last-command 'pop-to-mark-command)
-    (if (and (consp arg) (> (prefix-numeric-value arg) 4))
-       (push-mark-command nil)
-      (setq this-command 'pop-to-mark-command)
-      (pop-to-mark-command)))
+    (setq this-command 'pop-to-mark-command)
+    (pop-to-mark-command))
+   ((and (eq last-command 'pop-global-mark) (not arg))
+    (setq this-command 'pop-global-mark)
+    (pop-global-mark))
    (arg
     (setq this-command 'pop-to-mark-command)
     (pop-to-mark-command))
@@ -2389,13 +2576,11 @@ Novice Emacs Lisp programmers often try to use the mark for the wrong
 purposes.  See the documentation of `set-mark' for more information.
 
 In Transient Mark mode, this does not activate the mark."
-  (if (null (mark t))
-      nil
+  (unless (null (mark t))
     (setq mark-ring (cons (copy-marker (mark-marker)) mark-ring))
-    (if (> (length mark-ring) mark-ring-max)
-       (progn
-         (move-marker (car (nthcdr mark-ring-max mark-ring)) nil)
-         (setcdr (nthcdr (1- mark-ring-max) mark-ring) nil))))
+    (when (> (length mark-ring) mark-ring-max)
+      (move-marker (car (nthcdr mark-ring-max mark-ring)) nil)
+      (setcdr (nthcdr (1- mark-ring-max) mark-ring) nil)))
   (set-marker (mark-marker) (or location (point)) (current-buffer))
   ;; Now push the mark on the global mark ring.
   (if (and global-mark-ring
@@ -2404,11 +2589,9 @@ In Transient Mark mode, this does not activate the mark."
       ;; Don't push another one.
       nil
     (setq global-mark-ring (cons (copy-marker (mark-marker)) global-mark-ring))
-    (if (> (length global-mark-ring) global-mark-ring-max)
-       (progn
-         (move-marker (car (nthcdr global-mark-ring-max global-mark-ring))
-                      nil)
-         (setcdr (nthcdr (1- global-mark-ring-max) global-mark-ring) nil))))
+    (when (> (length global-mark-ring) global-mark-ring-max)
+      (move-marker (car (nthcdr global-mark-ring-max global-mark-ring)) nil)
+      (setcdr (nthcdr (1- global-mark-ring-max) global-mark-ring) nil)))
   (or nomsg executing-kbd-macro (> (minibuffer-depth) 0)
       (message "Mark set"))
   (if (or activate (not transient-mark-mode))
@@ -2418,14 +2601,13 @@ In Transient Mark mode, this does not activate the mark."
 (defun pop-mark ()
   "Pop off mark ring into the buffer's actual mark.
 Does not set point.  Does nothing if mark ring is empty."
-  (if mark-ring
-      (progn
-       (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)))))
+  (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))))
 
 (defalias 'exchange-dot-and-mark 'exchange-point-and-mark)
 (defun exchange-point-and-mark (&optional arg)
@@ -2435,7 +2617,7 @@ and it reactivates the mark.
 With prefix arg, `transient-mark-mode' is enabled temporarily."
   (interactive "P")
   (if arg
-      (if mark-active 
+      (if mark-active
          (if (null transient-mark-mode)
              (setq transient-mark-mode 'lambda))
        (setq arg nil)))
@@ -2447,7 +2629,7 @@ With prefix arg, `transient-mark-mode' is enabled temporarily."
       (goto-char omark)
       nil)))
 
-(defun transient-mark-mode (arg)
+(define-minor-mode transient-mark-mode
   "Toggle Transient Mark mode.
 With arg, turn Transient Mark mode on if arg is positive, off otherwise.
 
@@ -2468,15 +2650,7 @@ default part of the buffer's text.  Examples of such commands include
 \\[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."
-  (interactive "P")
-  (setq transient-mark-mode
-       (if (null arg)
-           (not transient-mark-mode)
-         (> (prefix-numeric-value arg) 0)))
-  (if (interactive-p)
-      (if transient-mark-mode
-         (message "Transient Mark mode enabled")
-       (message "Transient Mark mode disabled"))))
+  :global t :group 'editing-basics :require nil)
 
 (defun pop-global-mark ()
   "Pop off global mark ring and jump to the top location."
@@ -2525,7 +2699,7 @@ 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")
-  (unless arg (setq arg 1))
+  (or arg (setq arg 1))
   (if (and next-line-add-newlines (= arg 1))
       (if (save-excursion (end-of-line) (eobp))
          ;; When adding a newline, don't expand an abbrev.
@@ -2557,7 +2731,7 @@ 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")
-  (unless arg (setq arg 1))
+  (or arg (setq arg 1))
   (if (interactive-p)
       (condition-case nil
          (line-move (- arg))
@@ -2929,17 +3103,19 @@ With argument 0, interchanges line point is in with line mark is in."
   (if (> (cdr pos1) (car pos2)) (error "Don't have two things to transpose"))
   (atomic-change-group
    (let (word2)
+     ;; FIXME: We first delete the two pieces of text, so markers that
+     ;; used to point to after the text end up pointing to before it :-(
      (setq word2 (delete-and-extract-region (car pos2) (cdr pos2)))
      (goto-char (car pos2))
      (insert (delete-and-extract-region (car pos1) (cdr pos1)))
      (goto-char (car pos1))
      (insert word2))))
 \f
-(defun backward-word (arg)
+(defun backward-word (&optional arg)
   "Move backward until encountering the beginning of a word.
 With argument, do this that many times."
   (interactive "p")
-  (forward-word (- arg)))
+  (forward-word (- (or arg 1))))
 
 (defun mark-word (arg)
   "Set mark arg words away from point.
@@ -2971,37 +3147,42 @@ With argument, do this that many times."
   (interactive "p")
   (kill-word (- arg)))
 
-(defun current-word (&optional strict)
-  "Return the word point is on (or a nearby word) as a string.
+(defun current-word (&optional strict really-word)
+  "Return the symbol or word that point is on (or a nearby one) as a string.
+The return value includes no text properties.
 If optional arg STRICT is non-nil, return nil unless point is within
-or adjacent to a word."
+or adjacent to a symbol or word.
+The function, belying its name, normally finds a symbol.
+If optional arg REALLY-WORD is non-nil, it finds just a word."
   (save-excursion
-    (let ((oldpoint (point)) (start (point)) (end (point)))
-      (skip-syntax-backward "w_") (setq start (point))
+    (let* ((oldpoint (point)) (start (point)) (end (point))
+          (syntaxes (if really-word "w" "w_"))
+          (not-syntaxes (concat "^" syntaxes)))
+      (skip-syntax-backward syntaxes) (setq start (point))
       (goto-char oldpoint)
-      (skip-syntax-forward "w_") (setq end (point))
-      (if (and (eq start oldpoint) (eq end oldpoint))
-         ;; Point is neither within nor adjacent to a word.
-         (and (not strict)
-              (progn
-                ;; Look for preceding word in same line.
-                (skip-syntax-backward "^w_"
-                                      (save-excursion (beginning-of-line)
-                                                      (point)))
-                (if (bolp)
-                    ;; No preceding word in same line.
-                    ;; Look for following word in same line.
-                    (progn
-                      (skip-syntax-forward "^w_"
-                                           (save-excursion (end-of-line)
-                                                           (point)))
-                      (setq start (point))
-                      (skip-syntax-forward "w_")
-                      (setq end (point)))
-                  (setq end (point))
-                  (skip-syntax-backward "w_")
-                  (setq start (point)))
-                (buffer-substring-no-properties start end)))
+      (skip-syntax-forward syntaxes) (setq end (point))
+      (when (and (eq start oldpoint) (eq end oldpoint)
+                ;; Point is neither within nor adjacent to a word.
+                (not strict))
+       ;; Look for preceding word in same line.
+       (skip-syntax-backward not-syntaxes
+                             (save-excursion (beginning-of-line)
+                                             (point)))
+       (if (bolp)
+           ;; No preceding word in same line.
+           ;; Look for following word in same line.
+           (progn
+             (skip-syntax-forward not-syntaxes
+                                  (save-excursion (end-of-line)
+                                                  (point)))
+             (setq start (point))
+             (skip-syntax-forward syntaxes)
+             (setq end (point)))
+         (setq end (point))
+         (skip-syntax-backward syntaxes)
+         (setq start (point))))
+      ;; If we found something nonempty, return it as a string.
+      (unless (= start end)
        (buffer-substring-no-properties start end)))))
 \f
 (defcustom fill-prefix nil
@@ -3056,9 +3237,9 @@ Setting this variable automatically makes it local to the current buffer.")
          (and prefix (not (equal prefix ""))
               ;; Use auto-indentation rather than a guessed empty prefix.
               (not (and fill-indent-according-to-mode
-                        (string-match "[ \t]*" prefix)))
+                        (string-match "\\`[ \t]*\\'" prefix)))
               (setq fill-prefix prefix))))
-      
+
       (while (and (not give-up) (> (current-column) fc))
        ;; Determine where to split the line.
        (let* (after-prefix
@@ -3123,6 +3304,8 @@ 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.")
 
+;; FIXME: turn into a proper minor mode.
+;; Add a global minor mode version of it.
 (defun auto-fill-mode (&optional arg)
   "Toggle Auto Fill mode.
 With arg, turn Auto Fill mode on if and only if arg is positive.
@@ -3189,6 +3372,28 @@ The variable `selective-display' has a separate value for each buffer."
   (prin1 selective-display t)
   (princ "." t))
 
+(defvaralias 'indicate-unused-lines 'indicate-empty-lines)
+(defvaralias 'default-indicate-unused-lines 'default-indicate-empty-lines)
+
+(defun toggle-truncate-lines (arg)
+  "Toggle whether to fold or truncate long lines on the screen.
+With arg, truncate long lines iff arg is positive.
+Note that in side-by-side windows, truncation is always enabled."
+  (interactive "P")
+  (setq truncate-lines
+       (if (null arg)
+           (not truncate-lines)
+         (> (prefix-numeric-value arg) 0)))
+  (force-mode-line-update)
+  (unless truncate-lines
+    (let ((buffer (current-buffer)))
+      (walk-windows (lambda (window)
+                     (if (eq buffer (window-buffer window))
+                         (set-window-hscroll window 0)))
+                   nil t)))
+  (message "Truncate long lines %s"
+          (if truncate-lines "enabled" "disabled")))
+
 (defvar overwrite-mode-textual " Ovwrt"
   "The string displayed in the mode line when in overwrite mode.")
 (defvar overwrite-mode-binary " Bin Ovwrt"
@@ -3232,12 +3437,7 @@ specialization of overwrite-mode, entered by setting the
            'overwrite-mode-binary))
   (force-mode-line-update))
 
-(defcustom line-number-mode t
-  "*Non-nil means display line number in mode line."
-  :type 'boolean
-  :group 'editing-basics)
-
-(defun line-number-mode (arg)
+(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
@@ -3246,27 +3446,14 @@ 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'
 and `line-number-display-limit-width'."
-  (interactive "P")
-  (setq line-number-mode
-       (if (null arg) (not line-number-mode)
-         (> (prefix-numeric-value arg) 0)))
-  (force-mode-line-update))
-
-(defcustom column-number-mode nil
-  "*Non-nil means display column number in mode line."
-  :type 'boolean
-  :group 'editing-basics)
+  :init-value t :global t :group 'editing-basics :require nil)
 
-(defun column-number-mode (arg)
+(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."
-  (interactive "P")
-  (setq column-number-mode
-       (if (null arg) (not column-number-mode)
-         (> (prefix-numeric-value arg) 0)))
-  (force-mode-line-update))
+  :global t :group 'editing-basics :require nil)
 \f
 (defgroup paren-blinking nil
   "Blinking matching of parens and expressions."
@@ -3313,7 +3500,8 @@ when it is off screen)."
                           (point)))))
        (let* ((oldpos (point))
              (blinkpos)
-             (mismatch))
+             (mismatch)
+             matching-paren)
         (save-excursion
           (save-restriction
             (if blink-matching-paren-distance
@@ -3327,12 +3515,20 @@ when it is off screen)."
                   (setq blinkpos (scan-sexps oldpos -1)))
               (error nil)))
           (and blinkpos
-               (/= (char-syntax (char-after blinkpos))
-                   ?\$)
-               (setq mismatch
-                     (or (null (matching-paren (char-after blinkpos)))
+               (save-excursion
+                 (goto-char blinkpos)
+                 (not (looking-at "\\s$")))
+               (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)))
+                     mismatch
+                     (or (null matching-paren)
                          (/= (char-after (1- oldpos))
-                             (matching-paren (char-after blinkpos))))))
+                             matching-paren))))
           (if mismatch (setq blinkpos nil))
           (if blinkpos
               ;; Don't log messages about paren matching.
@@ -3392,6 +3588,7 @@ During execution of Lisp code, this character causes a quit directly.
 At top-level, as an editor command, this simply beeps."
   (interactive)
   (deactivate-mark)
+  (setq defining-kbd-macro nil)
   (signal 'quit nil))
 
 (define-key global-map "\C-g" 'keyboard-quit)
@@ -3490,41 +3687,6 @@ See also `read-mail-command' concerning reading mail."
                (function :tag "Other"))
   :group 'mail)
 
-(defun define-mail-user-agent (symbol composefunc sendfunc
-                                     &optional abortfunc hookvar)
-  "Define a symbol to identify a mail-sending package for `mail-user-agent'.
-
-SYMBOL can be any Lisp symbol.  Its function definition and/or
-value as a variable do not matter for this usage; we use only certain
-properties on its property list, to encode the rest of the arguments.
-
-COMPOSEFUNC is program callable function that composes an outgoing
-mail message buffer.  This function should set up the basics of the
-buffer without requiring user interaction.  It should populate the
-standard mail headers, leaving the `to:' and `subject:' headers blank
-by default.
-
-COMPOSEFUNC should accept several optional arguments--the same
-arguments that `compose-mail' takes.  See that function's documentation.
-
-SENDFUNC is the command a user would run to send the message.
-
-Optional ABORTFUNC is the command a user would run to abort the
-message.  For mail packages that don't have a separate abort function,
-this can be `kill-buffer' (the equivalent of omitting this argument).
-
-Optional HOOKVAR is a hook variable that gets run before the message
-is actually sent.  Callers that use the `mail-user-agent' may
-install a hook function temporarily on this hook variable.
-If HOOKVAR is nil, `mail-send-hook' is used.
-
-The properties used on SYMBOL are `composefunc', `sendfunc',
-`abortfunc', and `hookvar'."
-  (put symbol 'composefunc composefunc)
-  (put symbol 'sendfunc sendfunc)
-  (put symbol 'abortfunc (or abortfunc 'kill-buffer))
-  (put symbol 'hookvar (or hookvar 'mail-send-hook)))
-
 (define-mail-user-agent 'sendmail-user-agent
   'sendmail-user-agent-compose
   'mail-send-and-exit)
@@ -3621,7 +3783,7 @@ Each action has the form (FUNCTION . ARGS)."
 (defvar set-variable-value-history nil
   "History of values entered with `set-variable'.")
 
-(defun set-variable (var val)
+(defun set-variable (var val &optional make-local)
   "Set VARIABLE to VALUE.  VALUE is a Lisp object.
 When using this interactively, enter a Lisp object for VALUE.
 If you want VALUE to be a string, you must surround it with doublequotes.
@@ -3631,7 +3793,9 @@ If VARIABLE has a `variable-interactive' property, that is used as if
 it were the arg to `interactive' (which see) to interactively read VALUE.
 
 If VARIABLE has been defined with `defcustom', then the type information
-in the definition is used to check that VALUE is valid."
+in the definition is used to check that VALUE is valid.
+
+With a prefix argument, set VARIABLE to VALUE buffer-locally."
   (interactive
    (let* ((default-var (variable-at-point))
           (var (if (symbolp default-var)
@@ -3640,7 +3804,13 @@ in the definition is used to check that VALUE is valid."
                  (read-variable "Set variable: ")))
                      (minibuffer-help-form '(describe-variable var))
                      (prop (get var 'variable-interactive))
-                     (prompt (format "Set %s to value: " var))
+                     (prompt (format "Set %s%s to value: " var
+                                     (cond ((local-variable-p var)
+                                            " (buffer-local)")
+                                           ((or current-prefix-arg
+                                                (local-variable-if-set-p var))
+                                            " buffer-locally")
+                                           (t " globally"))))
                      (val (if prop
                               ;; Use VAR's `variable-interactive' property
                               ;; as an interactive spec for prompting.
@@ -3650,8 +3820,11 @@ in the definition is used to check that VALUE is valid."
                             (read
                              (read-string prompt nil
                                           'set-variable-value-history)))))
-                (list var val)))
+                (list var val current-prefix-arg)))
 
+  (and (custom-variable-p var)
+       (not (get var 'custom-type))
+       (custom-load-symbol var))
   (let ((type (get var 'custom-type)))
     (when type
       ;; Match with custom type.
@@ -3660,6 +3833,10 @@ in the definition is used to check that VALUE is valid."
       (unless (widget-apply type :match val)
        (error "Value `%S' does not match type %S of %S"
               val (car type) var))))
+
+  (if make-local
+      (make-local-variable var))
+
   (set var val)
 
   ;; Force a thorough redisplay for the case that the variable
@@ -3773,14 +3950,17 @@ With prefix argument N, move N items (negative N means move backward)."
 ;; that can be found before POINT.
 (defun choose-completion-delete-max-match (string)
   (let ((opoint (point))
-       (len (min (length string)
-                 (- (point) (point-min)))))
-    (goto-char (- (point) (length string)))
+       len)
+    ;; Try moving back by the length of the string.
+    (goto-char (max (- (point) (length string))
+                   (minibuffer-prompt-end)))
+    ;; See how far back we were actually able to move.  That is the
+    ;; upper bound on how much we can match and delete.
+    (setq len (- opoint (point)))
     (if completion-ignore-case
        (setq string (downcase string)))
     (while (and (> len 0)
-               (let ((tail (buffer-substring (point)
-                                             (+ (point) len))))
+               (let ((tail (buffer-substring (point) opoint)))
                  (if completion-ignore-case
                      (setq tail (downcase tail)))
                  (not (string= tail (substring string 0 len)))))
@@ -3793,7 +3973,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 iff BUFFER is a minibuffer, and
 BASE-SIZE - the number of characters in BUFFER before
 the string being completed.
 
@@ -3807,14 +3987,15 @@ the default method of inserting the completion in BUFFER.")
 (defun choose-completion-string (choice &optional buffer base-size)
   "Switch to BUFFER and insert the completion choice CHOICE.
 BASE-SIZE, if non-nil, says how many characters of BUFFER's text
-to keep.  If it is nil, use choose-completion-delete-max-match instead."
+to keep.  If it is nil, we call `choose-completion-delete-max-match'
+to decide what to delete."
 
   ;; If BUFFER is the minibuffer, exit the minibuffer
   ;; unless it is reading a file name and CHOICE is a directory,
   ;; or completion-no-auto-exit is non-nil.
 
-  (let ((buffer (or buffer completion-reference-buffer))
-       (mini-p (string-match "\\` \\*Minibuf-[0-9]+\\*\\'" (buffer-name buffer))))
+  (let* ((buffer (or buffer completion-reference-buffer))
+        (mini-p (minibufferp buffer)))
     ;; If BUFFER is a minibuffer, barf unless it's the currently
     ;; active minibuffer.
     (if (and mini-p
@@ -3822,9 +4003,10 @@ to keep.  If it is nil, use choose-completion-delete-max-match instead."
                 (not (equal buffer
                             (window-buffer (active-minibuffer-window))))))
        (error "Minibuffer is not active for completion")
-      (unless (run-hook-with-args-until-success 
-              'choose-completion-string-functions choice buffer mini-p base-size)
-       ;; Insert the completion into the buffer where completion was requested.
+      (unless (run-hook-with-args-until-success
+              'choose-completion-string-functions
+              choice buffer mini-p base-size)
+       ;; Insert the completion into the buffer where it was requested.
        (set-buffer buffer)
        (if base-size
            (delete-region (+ base-size (if mini-p
@@ -3886,12 +4068,19 @@ The completion list buffer is available as the value of `standard-output'.")
 
 (defun completion-setup-function ()
   (save-excursion
-    (let ((mainbuf (current-buffer)))
+    (let ((mainbuf (current-buffer))
+         (mbuf-contents (minibuffer-contents)))
+      ;; When reading a file name in the minibuffer,
+      ;; set default-directory in the minibuffer
+      ;; so it will get copied into the completion list buffer.
+      (if minibuffer-completing-file-name
+         (with-current-buffer mainbuf
+           (setq default-directory (file-name-directory mbuf-contents))))
       (set-buffer standard-output)
       (completion-list-mode)
       (make-local-variable 'completion-reference-buffer)
       (setq completion-reference-buffer mainbuf)
-      (if (eq minibuffer-completion-table 'read-file-name-internal)
+      (if minibuffer-completing-file-name
          ;; For file name completion,
          ;; use the number of chars before the start of the
          ;; last file name component.
@@ -3899,12 +4088,11 @@ The completion list buffer is available as the value of `standard-output'.")
                (save-excursion
                  (set-buffer mainbuf)
                  (goto-char (point-max))
-                 (skip-chars-backward (format "^%c" directory-sep-char))
+                 (skip-chars-backward "^/")
                  (- (point) (minibuffer-prompt-end))))
        ;; Otherwise, in minibuffer, the whole input is being completed.
        (save-match-data
-         (if (string-match "\\` \\*Minibuf-[0-9]+\\*\\'"
-                           (buffer-name mainbuf))
+         (if (minibufferp mainbuf)
              (setq completion-base-size 0))))
       (goto-char (point-min))
       (if (display-mouse-p)
@@ -3944,27 +4132,27 @@ select the completion near point.\n\n")))))
 ;; to the following event.
 
 (defun event-apply-alt-modifier (ignore-prompt)
-  "Add the Alt modifier to the following event.
+  "\\<function-key-map>Add the Alt modifier to the following event.
 For example, type \\[event-apply-alt-modifier] & to enter Alt-&."
   (vector (event-apply-modifier (read-event) 'alt 22 "A-")))
 (defun event-apply-super-modifier (ignore-prompt)
-  "Add the Super modifier to the following event.
+  "\\<function-key-map>Add the Super modifier to the following event.
 For example, type \\[event-apply-super-modifier] & to enter Super-&."
   (vector (event-apply-modifier (read-event) 'super 23 "s-")))
 (defun event-apply-hyper-modifier (ignore-prompt)
-  "Add the Hyper modifier to the following event.
+  "\\<function-key-map>Add the Hyper modifier to the following event.
 For example, type \\[event-apply-hyper-modifier] & to enter Hyper-&."
   (vector (event-apply-modifier (read-event) 'hyper 24 "H-")))
 (defun event-apply-shift-modifier (ignore-prompt)
-  "Add the Shift modifier to the following event.
+  "\\<function-key-map>Add the Shift modifier to the following event.
 For example, type \\[event-apply-shift-modifier] & to enter Shift-&."
   (vector (event-apply-modifier (read-event) 'shift 25 "S-")))
 (defun event-apply-control-modifier (ignore-prompt)
-  "Add the Ctrl modifier to the following event.
+  "\\<function-key-map>Add the Ctrl modifier to the following event.
 For example, type \\[event-apply-control-modifier] & to enter Ctrl-&."
   (vector (event-apply-modifier (read-event) 'control 26 "C-")))
 (defun event-apply-meta-modifier (ignore-prompt)
-  "Add the Meta modifier to the following event.
+  "\\<function-key-map>Add the Meta modifier to the following event.
 For example, type \\[event-apply-meta-modifier] & to enter Meta-&."
   (vector (event-apply-modifier (read-event) 'meta 27 "M-")))
 
@@ -4055,7 +4243,8 @@ Returns nil if PROCESS has already terminated."
                (let ((args (process-contact process t)))
                  (setq args (plist-put args :name newname))
                  (setq args (plist-put args :buffer
-                                       (if (process-buffer process) (current-buffer))))
+                                       (if (process-buffer process)
+                                           (current-buffer))))
                  (apply 'make-network-process args))
              (apply 'start-process newname
                     (if (process-buffer process) (current-buffer))
@@ -4066,6 +4255,7 @@ Returns nil if PROCESS has already terminated."
        new-process (process-inherit-coding-system-flag process))
       (set-process-filter new-process (process-filter process))
       (set-process-sentinel new-process (process-sentinel process))
+      (set-process-plist new-process (copy-sequence (process-plist process)))
       new-process)))
 
 ;; things to maybe add (currently partly covered by `funcall mode'):
@@ -4291,8 +4481,34 @@ See also `normal-erase-is-backspace'."
   (if (interactive-p)
       (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.")
+
+(define-minor-mode visible-mode
+  "Toggle Visible mode.
+With argument ARG turn Visible mode on iff ARG is positive.
+
+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"
+  (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))
+  (when visible-mode
+    (set (make-local-variable 'vis-mode-saved-buffer-invisibility-spec)
+        buffer-invisibility-spec)
+    (setq buffer-invisibility-spec nil)))
+\f
 ;; Minibuffer prompt stuff.
 
 ;(defun minibuffer-prompt-modification (start end)
@@ -4309,9 +4525,12 @@ See also `normal-erase-is-backspace'."
 ;    (message "You cannot modify the prompt")))
 ;
 ;
-;(setq minibuffer-prompt-properties 
+;(setq minibuffer-prompt-properties
 ;  (list 'modification-hooks '(minibuffer-prompt-modification)
 ;      'insert-in-front-hooks '(minibuffer-prompt-insertion)))
-;  
+;
+
+(provide 'simple)
 
+;;; arch-tag: 24af67c0-2a49-44f6-b3b1-312d8b570dfd
 ;;; simple.el ends here