Fixed.
[elisp/epg.git] / epa.el
diff --git a/epa.el b/epa.el
index ca47d02..40cc0ab 100644 (file)
--- a/epa.el
+++ b/epa.el
@@ -61,6 +61,11 @@ the separate window."
   :type 'integer
   :group 'epa)
 
+(defcustom epa-mail-modes '(mail-mode message-mode)
+  "List of major-modes to compose mails."
+  :type 'list
+  :group 'epa)
+
 (defgroup epa-faces nil
   "Faces for epa-mode."
   :group 'epa)
@@ -561,6 +566,8 @@ If SECRET is non-nil, list secret keys instead of public keys."
       (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)
@@ -597,7 +604,8 @@ If SECRET is non-nil, list secret keys instead of public keys."
 
 (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))
 
@@ -618,7 +626,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
-                                      #'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)
@@ -636,7 +646,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
-                                      #'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))
@@ -670,15 +682,16 @@ d - Create a detached signature
 (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.  "
-                             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
@@ -698,7 +711,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
-                                      #'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)
@@ -721,7 +736,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
-                                      #'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)
@@ -739,7 +756,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
-                                        #'epa-progress-callback-function)
+                                        #'epa-progress-callback-function
+                                        "Decrypting...")
       (message "Decrypting...")
       (setq plain (epg-decrypt-string context (buffer-substring start end)))
       (message "Decrypting...done")
@@ -747,7 +765,7 @@ Don't use this command in Lisp programs!"
                   plain
                   (or coding-system-for-read
                       (get-text-property start 'epa-coding-system-used))))
-      (if (y-or-n-p "Replace the text in the region? ")
+      (if (y-or-n-p "Replace the original text? ")
          (let ((inhibit-read-only t)
                buffer-read-only)
            (delete-region start end)
@@ -759,6 +777,17 @@ Don't use this command in Lisp programs!"
          (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.
@@ -769,7 +798,7 @@ Don't use this command in Lisp programs!"
     (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-----$"
@@ -777,14 +806,11 @@ Don't use this command in Lisp programs!"
          (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))))))))
            (epa-decrypt-region armor-start armor-end)))))))
 
 ;;;###autoload
@@ -808,7 +834,8 @@ Don't use this command in Lisp programs!"
   (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)
@@ -858,18 +885,18 @@ Don't use this command in Lisp programs!"
 
 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)
-          (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))
-          (if current-prefix-arg
+          (if verbose
               (epa--read-signature-type)
             'clear))))
   (save-excursion
@@ -883,7 +910,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
-                                        #'epa-progress-callback-function)
+                                        #'epa-progress-callback-function
+                                        "Signing...")
       (message "Signing...")
       (setq signature (epg-sign-string context
                                       (epa--encode-coding-string
@@ -892,6 +920,7 @@ If no one is selected, default secret key is used.  "
                                       mode))
       (message "Signing...done")
       (delete-region start end)
+      (goto-char start)
       (add-text-properties (point)
                           (progn
                             (insert (epa--decode-coding-string
@@ -906,6 +935,23 @@ If no one is selected, default secret key is used.  "
                                 'start-open t
                                 'end-open t)))))
 
+(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)))
+
+(defun epa--mail-mode-p ()
+  (let ((pointer epa-mail-modes))
+    (while (and pointer
+               (epa--derived-mode-p (car pointer)))
+      (setq pointer (cdr pointer)))
+    pointer))
+
 ;;;###autoload
 (defun epa-sign (start end signers mode)
   "Sign the current buffer.
@@ -914,22 +960,22 @@ Don't use this command in Lisp programs!"
   (interactive
    (save-excursion
      (goto-char (point-min))
-     (if (and (or (eq major-mode 'mail-mode)
-                 (eq (derived-mode-class major-mode) 'mail-mode))
+     (if (and (epa--mail-mode-p)
              (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.
+     (let ((verbose current-prefix-arg))
+       (list (point) (point-max)
+            (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))
-          (if current-prefix-arg
-              (epa--read-signature-type)
-            'clear))))
+                                 nil t))
+            (if verbose
+                (epa--read-signature-type)
+              'clear)))))
   (epa-sign-region start end signers mode))
 
 ;;;###autoload
@@ -957,7 +1003,8 @@ 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
-                                        #'epa-progress-callback-function)
+                                        #'epa-progress-callback-function
+                                        "Encrypting...")
       (message "Encrypting...")
       (setq cipher (epg-encrypt-string context
                                       (epa--encode-coding-string
@@ -966,6 +1013,7 @@ If no one is selected, symmetric encryption will be performed.  "))))
                                       recipients))
       (message "Encrypting...done")
       (delete-region start end)
+      (goto-char start)
       (add-text-properties (point)
                           (progn
                             (insert cipher)
@@ -986,13 +1034,12 @@ Don't use this command in Lisp programs!"
    (save-excursion
      (let (recipients)
        (goto-char (point-min))
-       (when (or (eq major-mode 'mail-mode)
-                (eq (derived-mode-class major-mode) 'mail-mode))
+       (when (epa--mail-mode-p)
         (save-restriction
           (narrow-to-region (point)
-                            (progn
-                              (search-forward mail-header-separator nil 0)
-                              (match-beginning 0)))
+                            (if (search-forward mail-header-separator nil 0)
+                                (match-beginning 0)
+                              (point)))
           (setq recipients
                 (mail-strip-quoted-names
                  (mapconcat #'identity
@@ -1001,7 +1048,8 @@ Don't use this command in Lisp programs!"
                                    (mail-fetch-field "bcc" nil nil t))
                             ","))))
         (if recipients
-            (setq recipients (delete "" (split-string recipients "[ \t\n]+"))))
+            (setq recipients (delete ""
+                                     (split-string recipients "[ \t\n]+"))))
         (goto-char (point-min))
         (if (search-forward mail-header-separator nil t)
             (forward-line)))
@@ -1170,7 +1218,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
-                                      #'epa-progress-callback-function)
+                                      #'epa-progress-callback-function
+                                      "Signing keys...")
     (message "Signing keys...")
     (epg-sign-keys context keys local)
     (message "Signing keys...done")))