* epg.el (epg--start): Make the process-buffer unibyte.
[elisp/epg.git] / epa.el
diff --git a/epa.el b/epa.el
index 2af91fc..85421f2 100644 (file)
--- a/epa.el
+++ b/epa.el
@@ -27,7 +27,6 @@
 (require 'font-lock)
 (require 'widget)
 (eval-when-compile (require 'wid-edit))
 (require 'font-lock)
 (require 'widget)
 (eval-when-compile (require 'wid-edit))
-(require 'mail-utils)
 (require 'derived)
 
 (defgroup epa nil
 (require 'derived)
 
 (defgroup epa nil
@@ -176,7 +175,7 @@ the separate window."
 (defvar epa-info-buffer nil)
 (defvar epa-last-coding-system-specified nil)
 
 (defvar epa-info-buffer nil)
 (defvar epa-last-coding-system-specified nil)
 
-(defvar epa-keys-mode-map
+(defvar epa-key-list-mode-map
   (let ((keymap (make-sparse-keymap)))
     (define-key keymap "m" 'epa-mark)
     (define-key keymap "u" 'epa-unmark)
   (let ((keymap (make-sparse-keymap)))
     (define-key keymap "m" 'epa-mark)
     (define-key keymap "u" 'epa-unmark)
@@ -255,22 +254,22 @@ the separate window."
     (defalias 'epa--decode-coding-string 'decode-coding-string)
   (defalias 'epa--decode-coding-string 'identity))
 
     (defalias 'epa--decode-coding-string 'decode-coding-string)
   (defalias 'epa--decode-coding-string 'identity))
 
-(defun epa-keys-mode ()
+(defun epa-key-list-mode ()
   "Major mode for `epa-list-keys'."
   (kill-all-local-variables)
   (buffer-disable-undo)
   "Major mode for `epa-list-keys'."
   (kill-all-local-variables)
   (buffer-disable-undo)
-  (setq major-mode 'epa-keys-mode
+  (setq major-mode 'epa-key-list-mode
        mode-name "Keys"
        truncate-lines t
        buffer-read-only t)
        mode-name "Keys"
        truncate-lines t
        buffer-read-only t)
-  (use-local-map epa-keys-mode-map)
+  (use-local-map epa-key-list-mode-map)
   (make-local-variable 'font-lock-defaults)
   (setq font-lock-defaults '(epa-font-lock-keywords t))
   ;; In XEmacs, auto-initialization of font-lock is not effective
   ;; if buffer-file-name is not set.
   (font-lock-set-defaults)
   (make-local-variable 'epa-exit-buffer-function)
   (make-local-variable 'font-lock-defaults)
   (setq font-lock-defaults '(epa-font-lock-keywords t))
   ;; In XEmacs, auto-initialization of font-lock is not effective
   ;; if buffer-file-name is not set.
   (font-lock-set-defaults)
   (make-local-variable 'epa-exit-buffer-function)
-  (run-hooks 'epa-keys-mode-hook))
+  (run-hooks 'epa-key-list-mode-hook))
 
 (defun epa-key-mode ()
   "Major mode for a key description."
 
 (defun epa-key-mode ()
   "Major mode for a key description."
@@ -348,6 +347,7 @@ reads the public keyring."
               (buffer-live-p epa-keys-buffer))
     (setq epa-keys-buffer (generate-new-buffer "*Keys*")))
   (set-buffer epa-keys-buffer)
               (buffer-live-p epa-keys-buffer))
     (setq epa-keys-buffer (generate-new-buffer "*Keys*")))
   (set-buffer epa-keys-buffer)
+  (epa-key-list-mode)
   (let ((inhibit-read-only t)
        buffer-read-only
        (point (point-min))
   (let ((inhibit-read-only t)
        buffer-read-only
        (point (point-min))
@@ -360,7 +360,6 @@ reads the public keyring."
                         (point-max)))
       (goto-char point))
     (epa--insert-keys context name mode)
                         (point-max)))
       (goto-char point))
     (epa--insert-keys context name mode)
-    (epa-keys-mode)
     (widget-setup)
     (set-keymap-parent (current-local-map) widget-keymap))
   (make-local-variable 'epa-list-keys-arguments)
     (widget-setup)
     (set-keymap-parent (current-local-map) widget-keymap))
   (make-local-variable 'epa-list-keys-arguments)
@@ -421,11 +420,15 @@ If SECRET is non-nil, list secret keys instead of public keys."
     (unless (and epa-keys-buffer
                 (buffer-live-p epa-keys-buffer))
       (setq epa-keys-buffer (generate-new-buffer "*Keys*")))
     (unless (and epa-keys-buffer
                 (buffer-live-p epa-keys-buffer))
       (setq epa-keys-buffer (generate-new-buffer "*Keys*")))
+    (set-buffer epa-keys-buffer)
+    (epa-key-list-mode)
     (let ((inhibit-read-only t)
          buffer-read-only)
     (let ((inhibit-read-only t)
          buffer-read-only)
-      (set-buffer epa-keys-buffer)
       (erase-buffer)
       (erase-buffer)
-      (insert prompt "\n")
+      (insert prompt "\n"
+             (substitute-command-keys "\
+- `\\[epa-mark]' to mark a key on the line
+- `\\[epa-unmark]' to unmark a key on the line\n"))
       (widget-create 'link
                     :notify (lambda (&rest ignore) (abort-recursive-edit))
                     :help-echo
       (widget-create 'link
                     :notify (lambda (&rest ignore) (abort-recursive-edit))
                     :help-echo
@@ -452,7 +455,6 @@ If SECRET is non-nil, list secret keys instead of public keys."
              (if (get-text-property (point) 'epa-list-keys)
                  (epa-mark)))
          (epa--insert-keys context nil nil)))
              (if (get-text-property (point) 'epa-list-keys)
                  (epa-mark)))
          (epa--insert-keys context nil nil)))
-      (epa-keys-mode)
       (widget-setup)
       (set-keymap-parent (current-local-map) widget-keymap)
       (setq epa-exit-buffer-function #'abort-recursive-edit)
       (widget-setup)
       (set-keymap-parent (current-local-map) widget-keymap)
       (setq epa-exit-buffer-function #'abort-recursive-edit)
@@ -501,6 +503,7 @@ If SECRET is non-nil, list secret keys instead of public keys."
       (setcdr entry (generate-new-buffer
                     (format "*Key*%s" (epg-sub-key-id primary-sub-key)))))
     (set-buffer (cdr entry))
       (setcdr entry (generate-new-buffer
                     (format "*Key*%s" (epg-sub-key-id primary-sub-key)))))
     (set-buffer (cdr entry))
+    (epa-key-mode)
     (make-local-variable 'epa-key)
     (setq epa-key key)
     (erase-buffer)
     (make-local-variable 'epa-key)
     (setq epa-key key)
     (erase-buffer)
@@ -553,14 +556,15 @@ If SECRET is non-nil, list secret keys instead of public keys."
              "\n")
       (setq pointer (cdr pointer)))
     (goto-char (point-min))
              "\n")
       (setq pointer (cdr pointer)))
     (goto-char (point-min))
-    (pop-to-buffer (current-buffer))
-    (epa-key-mode)))
+    (pop-to-buffer (current-buffer))))
 
 (defun epa-display-info (info)
   (if epa-popup-info-window
       (save-selected-window
        (unless epa-info-buffer
          (setq epa-info-buffer (generate-new-buffer "*Info*")))
 
 (defun epa-display-info (info)
   (if epa-popup-info-window
       (save-selected-window
        (unless epa-info-buffer
          (setq epa-info-buffer (generate-new-buffer "*Info*")))
+       (if (get-buffer-window epa-info-buffer)
+           (delete-window (get-buffer-window epa-info-buffer)))
        (save-excursion
          (set-buffer epa-info-buffer)
          (let ((inhibit-read-only t)
        (save-excursion
          (set-buffer epa-info-buffer)
          (let ((inhibit-read-only t)
@@ -597,7 +601,8 @@ If SECRET is non-nil, list secret keys instead of public keys."
 
 (defun epa-progress-callback-function (context what char current total
                                               handback)
 
 (defun epa-progress-callback-function (context what char current total
                                               handback)
-  (message "%s: %d%% (%d/%d)" what
+  (message "%s%d%% (%d/%d)" (or handback
+                               (concat what ": "))
           (if (> total 0) (floor (* (/ current (float total)) 100)) 0)
           current total))
 
           (if (> total 0) (floor (* (/ current (float total)) 100)) 0)
           current total))
 
@@ -618,7 +623,9 @@ If SECRET is non-nil, list secret keys instead of public keys."
     (epg-context-set-passphrase-callback context
                                         #'epa-passphrase-callback-function)
     (epg-context-set-progress-callback context
     (epg-context-set-passphrase-callback context
                                         #'epa-passphrase-callback-function)
     (epg-context-set-progress-callback context
-                                      #'epa-progress-callback-function)
+                                      #'epa-progress-callback-function
+                                      (format "Decrypting %s..."
+                                              (file-name-nondirectory file)))
     (message "Decrypting %s..." (file-name-nondirectory file))
     (epg-decrypt-file context file plain)
     (message "Decrypting %s...wrote %s" (file-name-nondirectory file)
     (message "Decrypting %s..." (file-name-nondirectory file))
     (epg-decrypt-file context file plain)
     (message "Decrypting %s...wrote %s" (file-name-nondirectory file)
@@ -636,7 +643,9 @@ If SECRET is non-nil, list secret keys instead of public keys."
         (plain (if (equal (file-name-extension file) "sig")
                    (file-name-sans-extension file))))
     (epg-context-set-progress-callback context
         (plain (if (equal (file-name-extension file) "sig")
                    (file-name-sans-extension file))))
     (epg-context-set-progress-callback context
-                                      #'epa-progress-callback-function)
+                                      #'epa-progress-callback-function
+                                      (format "Verifying %s..."
+                                              (file-name-nondirectory file)))
     (message "Verifying %s..." (file-name-nondirectory file))
     (epg-verify-file context file plain)
     (message "Verifying %s...done" (file-name-nondirectory file))
     (message "Verifying %s..." (file-name-nondirectory file))
     (epg-verify-file context file plain)
     (message "Verifying %s...done" (file-name-nondirectory file))
@@ -670,15 +679,16 @@ d - Create a detached signature
 (defun epa-sign-file (file signers mode)
   "Sign FILE by SIGNERS keys selected."
   (interactive
 (defun epa-sign-file (file signers mode)
   "Sign FILE by SIGNERS keys selected."
   (interactive
-   (list (expand-file-name (read-file-name "File: "))
-        (if current-prefix-arg
-            (epa-select-keys (epg-make-context epa-protocol)
-                             "Select keys for signing.
+   (let ((verbose current-prefix-arg))
+     (list (expand-file-name (read-file-name "File: "))
+          (if verbose
+              (epa-select-keys (epg-make-context epa-protocol)
+                               "Select keys for signing.
 If no one is selected, default secret key is used.  "
 If no one is selected, default secret key is used.  "
-                             nil t))
-        (if current-prefix-arg
-            (epa--read-signature-type)
-          'clear)))
+                               nil t))
+          (if verbose
+              (epa--read-signature-type)
+            'clear))))
   (let ((signature (concat file
                           (if (eq epa-protocol 'OpenPGP)
                               (if (or epa-armor
   (let ((signature (concat file
                           (if (eq epa-protocol 'OpenPGP)
                               (if (or epa-armor
@@ -698,7 +708,9 @@ If no one is selected, default secret key is used.  "
     (epg-context-set-passphrase-callback context
                                         #'epa-passphrase-callback-function)
     (epg-context-set-progress-callback context
     (epg-context-set-passphrase-callback context
                                         #'epa-passphrase-callback-function)
     (epg-context-set-progress-callback context
-                                      #'epa-progress-callback-function)
+                                      #'epa-progress-callback-function
+                                      (format "Signing %s..."
+                                              (file-name-nondirectory file)))
     (message "Signing %s..." (file-name-nondirectory file))
     (epg-sign-file context file signature mode)
     (message "Signing %s...wrote %s" (file-name-nondirectory file)
     (message "Signing %s..." (file-name-nondirectory file))
     (epg-sign-file context file signature mode)
     (message "Signing %s...wrote %s" (file-name-nondirectory file)
@@ -721,7 +733,9 @@ If no one is selected, symmetric encryption will be performed.  ")))
     (epg-context-set-passphrase-callback context
                                         #'epa-passphrase-callback-function)
     (epg-context-set-progress-callback context
     (epg-context-set-passphrase-callback context
                                         #'epa-passphrase-callback-function)
     (epg-context-set-progress-callback context
-                                      #'epa-progress-callback-function)
+                                      #'epa-progress-callback-function
+                                      (format "Encrypting %s..."
+                                              (file-name-nondirectory file)))
     (message "Encrypting %s..." (file-name-nondirectory file))
     (epg-encrypt-file context file recipients cipher)
     (message "Encrypting %s...wrote %s" (file-name-nondirectory file)
     (message "Encrypting %s..." (file-name-nondirectory file))
     (epg-encrypt-file context file recipients cipher)
     (message "Encrypting %s...wrote %s" (file-name-nondirectory file)
@@ -739,20 +753,40 @@ Don't use this command in Lisp programs!"
       (epg-context-set-passphrase-callback context
                                           #'epa-passphrase-callback-function)
       (epg-context-set-progress-callback context
       (epg-context-set-passphrase-callback context
                                           #'epa-passphrase-callback-function)
       (epg-context-set-progress-callback context
-                                        #'epa-progress-callback-function)
+                                        #'epa-progress-callback-function
+                                        "Decrypting...")
       (message "Decrypting...")
       (setq plain (epg-decrypt-string context (buffer-substring start end)))
       (message "Decrypting...done")
       (message "Decrypting...")
       (setq plain (epg-decrypt-string context (buffer-substring start end)))
       (message "Decrypting...done")
-      (delete-region start end)
-      (goto-char start)
-      (insert (epa--decode-coding-string plain
-                                        (or coding-system-for-read
-                                            (get-text-property
-                                             start 'epa-coding-system-used))))
+      (setq plain (epa--decode-coding-string
+                  plain
+                  (or coding-system-for-read
+                      (get-text-property start 'epa-coding-system-used))))
+      (if (y-or-n-p "Replace the original text? ")
+         (let ((inhibit-read-only t)
+               buffer-read-only)
+           (delete-region start end)
+           (goto-char start)
+           (insert plain))
+       (with-output-to-temp-buffer "*Temp*"
+         (set-buffer standard-output)
+         (insert plain)
+         (epa-info-mode)))
       (if (epg-context-result-for context 'verify)
          (epa-display-info (epg-verify-result-to-string
                             (epg-context-result-for context 'verify)))))))
 
       (if (epg-context-result-for context 'verify)
          (epa-display-info (epg-verify-result-to-string
                             (epg-context-result-for context 'verify)))))))
 
+(defun epa--find-coding-system-for-mime-charset (mime-charset)
+  (if (featurep 'xemacs)
+      (if (fboundp 'find-coding-system)
+         (find-coding-system mime-charset))
+    (let ((pointer (coding-system-list)))
+      (while (and pointer
+                 (eq (coding-system-get (car pointer) 'mime-charset)
+                     mime-charset))
+       (setq pointer (cdr pointer)))
+      pointer)))
+
 ;;;###autoload
 (defun epa-decrypt-armor-in-region (start end)
   "Decrypt OpenPGP armors in the current region between START and END.
 ;;;###autoload
 (defun epa-decrypt-armor-in-region (start end)
   "Decrypt OpenPGP armors in the current region between START and END.
@@ -763,7 +797,7 @@ Don't use this command in Lisp programs!"
     (save-restriction
       (narrow-to-region start end)
       (goto-char start)
     (save-restriction
       (narrow-to-region start end)
       (goto-char start)
-      (let (armor-start armor-end charset coding-system)
+      (let (armor-start armor-end)
        (while (re-search-forward "-----BEGIN PGP MESSAGE-----$" nil t)
          (setq armor-start (match-beginning 0)
                armor-end (re-search-forward "^-----END PGP MESSAGE-----$"
        (while (re-search-forward "-----BEGIN PGP MESSAGE-----$" nil t)
          (setq armor-start (match-beginning 0)
                armor-end (re-search-forward "^-----END PGP MESSAGE-----$"
@@ -771,30 +805,15 @@ Don't use this command in Lisp programs!"
          (unless armor-end
            (error "No armor tail"))
          (goto-char armor-start)
          (unless armor-end
            (error "No armor tail"))
          (goto-char armor-start)
-         (if (re-search-forward "^Charset: \\(.*\\)" armor-end t)
-             (setq charset (match-string 1)))
-         (if coding-system-for-read
-             (setq coding-system coding-system-for-read)
-           (if charset
-               (setq coding-system (intern (downcase charset)))
-             (setq coding-system 'utf-8)))
-         (let ((coding-system-for-read coding-system))
+         (let ((coding-system-for-read
+                (or coding-system-for-read
+                    (if (re-search-forward "^Charset: \\(.*\\)" armor-end t)
+                        (epa--find-coding-system-for-mime-charset
+                         (intern (downcase (match-string 1))))))))
+           (goto-char armor-end)
            (epa-decrypt-region armor-start armor-end)))))))
 
 ;;;###autoload
            (epa-decrypt-region armor-start armor-end)))))))
 
 ;;;###autoload
-(defun epa-decrypt ()
-  "Decrypt OpenPGP armors in the current buffer.
-
-Don't use this command in Lisp programs!"
-  (interactive)
-  (epa-decrypt-armor-in-region (point-min) (point-max)))
-
-(if (fboundp 'select-safe-coding-system)
-    (defalias 'epa--select-safe-coding-system 'select-safe-coding-system)
-  (defun epa--select-safe-coding-system (from to)
-    buffer-file-coding-system))
-
-;;;###autoload
 (defun epa-verify-region (start end)
   "Verify the current region between START and END.
 
 (defun epa-verify-region (start end)
   "Verify the current region between START and END.
 
@@ -802,7 +821,8 @@ Don't use this command in Lisp programs!"
   (interactive "r")
   (let ((context (epg-make-context epa-protocol)))
     (epg-context-set-progress-callback context
   (interactive "r")
   (let ((context (epg-make-context epa-protocol)))
     (epg-context-set-progress-callback context
-                                      #'epa-progress-callback-function)
+                                      #'epa-progress-callback-function
+                                      "Verifying...")
     (epg-verify-string context
                       (epa--encode-coding-string
                        (buffer-substring start end)
     (epg-verify-string context
                       (epa--encode-coding-string
                        (buffer-substring start end)
@@ -838,12 +858,10 @@ Don't use this command in Lisp programs!"
            (error "No armor tail"))
          (epa-verify-region armor-start armor-end))))))
 
            (error "No armor tail"))
          (epa-verify-region armor-start armor-end))))))
 
-;;;###autoload
-(defun epa-verify ()
-  "Verify OpenPGP cleartext signed messages in the current buffer.
-
-Don't use this command in Lisp programs!"
-  (epa-verify-cleartext-in-region (point-min) (point-max)))
+(if (fboundp 'select-safe-coding-system)
+    (defalias 'epa--select-safe-coding-system 'select-safe-coding-system)
+  (defun epa--select-safe-coding-system (from to)
+    buffer-file-coding-system))
 
 ;;;###autoload
 (defun epa-sign-region (start end signers mode)
 
 ;;;###autoload
 (defun epa-sign-region (start end signers mode)
@@ -851,18 +869,18 @@ Don't use this command in Lisp programs!"
 
 Don't use this command in Lisp programs!"
   (interactive
 
 Don't use this command in Lisp programs!"
   (interactive
-   (progn
+   (let ((verbose current-prefix-arg))
      (setq epa-last-coding-system-specified
           (or coding-system-for-write
               (epa--select-safe-coding-system
                (region-beginning) (region-end))))
      (list (region-beginning) (region-end)
      (setq epa-last-coding-system-specified
           (or coding-system-for-write
               (epa--select-safe-coding-system
                (region-beginning) (region-end))))
      (list (region-beginning) (region-end)
-          (if current-prefix-arg
+          (if verbose
               (epa-select-keys (epg-make-context epa-protocol)
                                "Select keys for signing.
 If no one is selected, default secret key is used.  "
                                nil t))
               (epa-select-keys (epg-make-context epa-protocol)
                                "Select keys for signing.
 If no one is selected, default secret key is used.  "
                                nil t))
-          (if current-prefix-arg
+          (if verbose
               (epa--read-signature-type)
             'clear))))
   (save-excursion
               (epa--read-signature-type)
             'clear))))
   (save-excursion
@@ -876,7 +894,8 @@ If no one is selected, default secret key is used.  "
       (epg-context-set-passphrase-callback context
                                           #'epa-passphrase-callback-function)
       (epg-context-set-progress-callback context
       (epg-context-set-passphrase-callback context
                                           #'epa-passphrase-callback-function)
       (epg-context-set-progress-callback context
-                                        #'epa-progress-callback-function)
+                                        #'epa-progress-callback-function
+                                        "Signing...")
       (message "Signing...")
       (setq signature (epg-sign-string context
                                       (epa--encode-coding-string
       (message "Signing...")
       (setq signature (epg-sign-string context
                                       (epa--encode-coding-string
@@ -885,6 +904,7 @@ If no one is selected, default secret key is used.  "
                                       mode))
       (message "Signing...done")
       (delete-region start end)
                                       mode))
       (message "Signing...done")
       (delete-region start end)
+      (goto-char start)
       (add-text-properties (point)
                           (progn
                             (insert (epa--decode-coding-string
       (add-text-properties (point)
                           (progn
                             (insert (epa--decode-coding-string
@@ -899,47 +919,37 @@ If no one is selected, default secret key is used.  "
                                 'start-open t
                                 'end-open t)))))
 
                                 'start-open t
                                 'end-open t)))))
 
-;;;###autoload
-(defun epa-sign (start end signers mode)
-  "Sign the current buffer.
-
-Don't use this command in Lisp programs!"
-  (interactive
-   (progn
-     (goto-char (point-min))
-     (if (and (or (eq major-mode 'mail-mode)
-                 (eq (derived-mode-class major-mode) 'mail-mode))
-             (search-forward mail-header-separator nil t))
-        (forward-line))
-     (setq epa-last-coding-system-specified
-          (or coding-system-for-write
-              (epa--select-safe-coding-system (point) (point-max))))
-     (list (point) (point-max)
-          (if current-prefix-arg
-              (epa-select-keys (epg-make-context epa-protocol)
-                               "Select keys for signing.
-If no one is selected, default secret key is used.  "
-                               nil t))
-          (if current-prefix-arg
-              (epa--read-signature-type)
-            'clear))))
-  (epa-sign-region start end signers mode))
+(if (fboundp 'derived-mode-p)
+    (defalias 'epa--derived-mode-p 'derived-mode-p)
+  (defun epa--derived-mode-p (&rest modes)
+    "Non-nil if the current major mode is derived from one of MODES.
+Uses the `derived-mode-parent' property of the symbol to trace backwards."
+    (let ((parent major-mode))
+      (while (and (not (memq parent modes))
+                 (setq parent (get parent 'derived-mode-parent))))
+      parent)))
 
 ;;;###autoload
 
 ;;;###autoload
-(defun epa-encrypt-region (start end recipients)
+(defun epa-encrypt-region (start end recipients sign signers)
   "Encrypt the current region between START and END for RECIPIENTS.
 
 Don't use this command in Lisp programs!"
   (interactive
   "Encrypt the current region between START and END for RECIPIENTS.
 
 Don't use this command in Lisp programs!"
   (interactive
-   (progn
+   (let ((verbose current-prefix-arg)
+        (context (epg-make-context epa-protocol))
+        sign)
      (setq epa-last-coding-system-specified
           (or coding-system-for-write
               (epa--select-safe-coding-system
                (region-beginning) (region-end))))
      (list (region-beginning) (region-end)
      (setq epa-last-coding-system-specified
           (or coding-system-for-write
               (epa--select-safe-coding-system
                (region-beginning) (region-end))))
      (list (region-beginning) (region-end)
-          (epa-select-keys (epg-make-context epa-protocol)
+          (epa-select-keys context
                            "Select recipients for encryption.
                            "Select recipients for encryption.
-If no one is selected, symmetric encryption will be performed.  "))))
+If no one is selected, symmetric encryption will be performed.  ")
+          (setq sign (if verbose (y-or-n-p "Sign? ")))
+          (if sign
+              (epa-select-keys context
+                               "Select keys for signing.  ")))))
   (save-excursion
     (let ((context (epg-make-context epa-protocol))
          cipher)
   (save-excursion
     (let ((context (epg-make-context epa-protocol))
          cipher)
@@ -947,18 +957,23 @@ If no one is selected, symmetric encryption will be performed.  "))))
       (epg-context-set-armor context t)
       ;;(epg-context-set-textmode context epa-textmode)
       (epg-context-set-textmode context t)
       (epg-context-set-armor context t)
       ;;(epg-context-set-textmode context epa-textmode)
       (epg-context-set-textmode context t)
+      (if sign
+         (epg-context-set-signers context signers))
       (epg-context-set-passphrase-callback context
                                           #'epa-passphrase-callback-function)
       (epg-context-set-progress-callback context
       (epg-context-set-passphrase-callback context
                                           #'epa-passphrase-callback-function)
       (epg-context-set-progress-callback context
-                                        #'epa-progress-callback-function)
+                                        #'epa-progress-callback-function
+                                        "Encrypting...")
       (message "Encrypting...")
       (setq cipher (epg-encrypt-string context
                                       (epa--encode-coding-string
                                        (buffer-substring start end)
                                        epa-last-coding-system-specified)
       (message "Encrypting...")
       (setq cipher (epg-encrypt-string context
                                       (epa--encode-coding-string
                                        (buffer-substring start end)
                                        epa-last-coding-system-specified)
-                                      recipients))
+                                      recipients
+                                      sign))
       (message "Encrypting...done")
       (delete-region start end)
       (message "Encrypting...done")
       (delete-region start end)
+      (goto-char start)
       (add-text-properties (point)
                           (progn
                             (insert cipher)
       (add-text-properties (point)
                           (progn
                             (insert cipher)
@@ -971,53 +986,6 @@ If no one is selected, symmetric encryption will be performed.  "))))
                                 'end-open t)))))
 
 ;;;###autoload
                                 'end-open t)))))
 
 ;;;###autoload
-(defun epa-encrypt (start end recipients)
-  "Encrypt the current buffer.
-
-Don't use this command in Lisp programs!"
-  (interactive
-   (let (recipients)
-     (goto-char (point-min))
-     (when (or (eq major-mode 'mail-mode)
-              (eq (derived-mode-class major-mode) 'mail-mode))
-       (save-restriction
-        (narrow-to-region (point)
-                          (progn
-                            (search-forward mail-header-separator nil 0)
-                            (match-beginning 0)))
-        (setq recipients
-              (mail-strip-quoted-names
-               (mapconcat #'identity
-                          (nconc (mail-fetch-field "to" nil nil t)
-                                 (mail-fetch-field "cc" nil nil t)
-                                 (mail-fetch-field "bcc" nil nil t))
-                          ","))))
-       (if recipients
-          (setq recipients (delete "" (split-string recipients "[ \t\n]+"))))
-       (goto-char (point-min))
-       (if (search-forward mail-header-separator nil t)
-          (forward-line)))
-     (setq epa-last-coding-system-specified
-          (or coding-system-for-write
-              (epa--select-safe-coding-system (point) (point-max))))
-     (list (point) (point-max)
-          (if current-prefix-arg
-              (epa-select-keys
-               (epg-make-context epa-protocol)
-               "Select recipients for encryption.
-If no one is selected, symmetric encryption will be performed.  "
-               recipients)
-            (if recipients
-                (delq nil
-                      (apply #'nconc
-                             (mapcar
-                              (lambda (recipient)
-                                (epg-list-keys (epg-make-context epa-protocol)
-                                               (concat "<" recipient ">")))
-                              recipients))))))))
-  (epa-encrypt-region start end recipients))
-
-;;;###autoload
 (defun epa-delete-keys (keys &optional allow-secret)
   "Delete selected KEYS.
 
 (defun epa-delete-keys (keys &optional allow-secret)
   "Delete selected KEYS.
 
@@ -1052,7 +1020,7 @@ Don't use this command in Lisp programs!"
     (if (epg-context-result-for context 'import)
        (epa-display-info (epg-import-result-to-string
                           (epg-context-result-for context 'import))))
     (if (epg-context-result-for context 'import)
        (epa-display-info (epg-import-result-to-string
                           (epg-context-result-for context 'import))))
-    (if (eq major-mode 'epa-keys-mode)
+    (if (eq major-mode 'epa-key-list-mode)
        (apply #'epa-list-keys epa-list-keys-arguments))))
 
 ;;;###autoload
        (apply #'epa-list-keys epa-list-keys-arguments))))
 
 ;;;###autoload
@@ -1074,6 +1042,29 @@ Don't use this command in Lisp programs!"
                           (epg-context-result-for context 'import))))))
 
 ;;;###autoload
                           (epg-context-result-for context 'import))))))
 
 ;;;###autoload
+(defun epa-import-armor-in-region (start end)
+  "Import keys in the OpenPGP armor format in the current region
+between START and END.
+
+Don't use this command in Lisp programs!"
+  (interactive "r")
+  (save-excursion
+    (save-restriction
+      (narrow-to-region start end)
+      (goto-char start)
+      (let (armor-start armor-end)
+       (while (re-search-forward
+               "-----BEGIN \\(PGP \\(PUBLIC\\|PRIVATE\\) KEY BLOCK\\)-----$"
+               nil t)
+         (setq armor-start (match-beginning 0)
+               armor-end (re-search-forward
+                          (concat "^-----END " (match-string 1) "-----$")
+                          nil t))
+         (unless armor-end
+           (error "No armor tail"))
+         (epa-import-keys-region armor-start armor-end))))))
+
+;;;###autoload
 (defun epa-export-keys (keys file)
   "Export selected KEYS to FILE.
 
 (defun epa-export-keys (keys file)
   "Export selected KEYS to FILE.
 
@@ -1130,7 +1121,8 @@ Don't use this command in Lisp programs!"
     (epg-context-set-passphrase-callback context
                                         #'epa-passphrase-callback-function)
     (epg-context-set-progress-callback context
     (epg-context-set-passphrase-callback context
                                         #'epa-passphrase-callback-function)
     (epg-context-set-progress-callback context
-                                      #'epa-progress-callback-function)
+                                      #'epa-progress-callback-function
+                                      "Signing keys...")
     (message "Signing keys...")
     (epg-sign-keys context keys local)
     (message "Signing keys...done")))
     (message "Signing keys...")
     (epg-sign-keys context keys local)
     (message "Signing keys...done")))