Convert consecutive FSF copyright years to ranges.
[bpt/emacs.git] / lisp / mail / rmail.el
index b690a00..70bfb09 100644 (file)
@@ -1,7 +1,6 @@
 ;;; rmail.el --- main code of "RMAIL" mail reader for Emacs
 
-;; Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1996, 1997, 1998,
-;;   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+;; Copyright (C) 1985-1988, 1993-1998, 2000-2011
 ;;   Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
@@ -39,6 +38,7 @@
 ;;
 
 (require 'mail-utils)
+(require 'rfc2047)
 
 (defconst rmail-attribute-header "X-RMAIL-ATTRIBUTES"
   "The header that stores the Rmail attribute data.")
@@ -191,8 +191,6 @@ please report it with \\[report-emacs-bug].")
   :group 'rmail-retrieve
   :type '(repeat (directory)))
 
-(declare-function mail-position-on-field "sendmail" (field &optional soft))
-(declare-function mail-text-start "sendmail" ())
 (declare-function rmail-dont-reply-to "mail-utils" (destinations))
 (declare-function rmail-update-summary "rmailsum" (&rest ignore))
 
@@ -297,7 +295,7 @@ also the To field, unless this would leave an empty To field."
   :group 'rmail-reply)
 
 ;;;###autoload
-(defvar rmail-default-dont-reply-to-names "\\`info-"
+(defvar rmail-default-dont-reply-to-names (purecopy "\\`info-")
   "Regexp specifying part of the default value of `rmail-dont-reply-to-names'.
 This is used when the user does not set `rmail-dont-reply-to-names'
 explicitly.  (The other part of the default value is the user's
@@ -308,6 +306,7 @@ used for large mailing lists to broadcast announcements.")
 
 ;;;###autoload
 (defcustom rmail-ignored-headers
+  (purecopy
   (concat "^via:\\|^mail-from:\\|^origin:\\|^references:\\|^sender:"
          "\\|^status:\\|^received:\\|^x400-originator:\\|^x400-recipients:"
          "\\|^x400-received:\\|^x400-mts-identifier:\\|^x400-content-type:"
@@ -324,7 +323,7 @@ used for large mailing lists to broadcast announcements.")
          "\\|^mbox-line:\\|^cancel-lock:"
          "\\|^DomainKey-Signature:\\|^dkim-signature:"
          "\\|^resent-face:\\|^resent-x.*:\\|^resent-organization:\\|^resent-openpgp:"
-         "\\|^x-.*:")
+         "\\|^x-.*:"))
   "Regexp to match header fields that Rmail should normally hide.
 \(See also `rmail-nonignored-headers', which overrides this regexp.)
 This variable is used for reformatting the message header,
@@ -360,14 +359,14 @@ If nil, display all header fields except those matched by
   :group 'rmail-headers)
 
 ;;;###autoload
-(defcustom rmail-retry-ignored-headers "^x-authentication-warning:\\|^x-detected-operating-system:\\|^x-spam[-a-z]*:\\|content-type:\\|content-transfer-encoding:\\|mime-version:"
+(defcustom rmail-retry-ignored-headers (purecopy "^x-authentication-warning:\\|^x-detected-operating-system:\\|^x-spam[-a-z]*:\\|content-type:\\|content-transfer-encoding:\\|mime-version:")
   "Headers that should be stripped when retrying a failed message."
   :type '(choice regexp (const nil :tag "None"))
   :group 'rmail-headers
   :version "23.2")        ; added x-detected-operating-system, x-spam
 
 ;;;###autoload
-(defcustom rmail-highlighted-headers "^From:\\|^Subject:"
+(defcustom rmail-highlighted-headers (purecopy "^From:\\|^Subject:")
   "Regexp to match Header fields that Rmail should normally highlight.
 A value of nil means don't highlight.  Uses the face `rmail-highlight'."
   :type 'regexp
@@ -380,6 +379,20 @@ The variable `rmail-highlighted-headers' specifies which headers."
   :group 'rmail-headers
   :version "22.1")
 
+;; This was removed in Emacs 23.1 with no notification, an unnecessary
+;; incompatible change.
+(defcustom rmail-highlight-face 'rmail-highlight
+  "Face used by Rmail for highlighting headers."
+  ;; Note that nil doesn't actually mean use the default face, it
+  ;; means use either bold or highlight. It's not worth fixing this
+  ;; now that this is obsolete.
+  :type '(choice (const :tag "Default" nil)
+                face)
+  :group 'rmail-headers)
+(make-obsolete-variable 'rmail-highlight-face
+                       "customize the face `rmail-highlight' instead."
+                       "23.2")
+
 (defface rmail-header-name
   '((t (:inherit font-lock-function-name-face)))
   "Face to use for highlighting the header names.
@@ -418,12 +431,12 @@ the frame where you have the RMAIL buffer displayed."
   :group 'rmail-reply)
 
 ;;;###autoload
-(defcustom rmail-secondary-file-directory "~/"
+(defcustom rmail-secondary-file-directory (purecopy "~/")
   "Directory for additional secondary Rmail files."
   :type 'directory
   :group 'rmail-files)
 ;;;###autoload
-(defcustom rmail-secondary-file-regexp "\\.xmail$"
+(defcustom rmail-secondary-file-regexp (purecopy "\\.xmail$")
   "Regexp for which files are secondary Rmail files."
   :type 'regexp
   :group 'rmail-files)
@@ -625,7 +638,7 @@ Element N specifies the summary line for message N+1.")
 
 This is set to nil by default.")
 
-(defcustom rmail-enable-mime nil
+(defcustom rmail-enable-mime t
   "If non-nil, RMAIL uses MIME features.
 If the value is t, RMAIL automatically shows MIME decoded message.
 If the value is neither t nor nil, RMAIL does not show MIME decoded message
@@ -636,6 +649,7 @@ unless the feature specified by `rmail-mime-feature' is available."
   :type '(choice (const :tag "on" t)
                 (const :tag "off" nil)
                 (other :tag "when asked" ask))
+  :version "23.3"
   :group 'rmail)
 
 (defvar rmail-enable-mime-composing nil
@@ -680,13 +694,12 @@ start of the header) with three arguments MSG, REGEXP, and LIMIT,
 where MSG is the message number, REGEXP is the regular
 expression, LIMIT is the position specifying the end of header.")
 
-(defvar rmail-mime-feature 'rmail-mime
+(defvar rmail-mime-feature 'rmailmm
   "Feature to require to load MIME support in Rmail.
 When starting Rmail, if `rmail-enable-mime' is non-nil,
 this feature is required with `require'.
 
-The default value is `rmail-mime'.  This feature is provided by
-the rmail-mime package available at <http://www.m17n.org/rmail-mime/>.")
+The default value is `rmailmm'")
 
 ;; FIXME this is unused.
 (defvar rmail-decode-mime-charset t
@@ -791,6 +804,12 @@ that knows the exact ordering of the \\( \\) subexpressions.")
              . 'rmail-header-name))))
   "Additional expressions to highlight in Rmail mode.")
 
+;; Rmail does not expect horizontal splitting.  (Bug#2282)
+(defun rmail-pop-to-buffer (&rest args)
+  "Like `pop-to-buffer', but with `split-width-threshold' set to nil."
+  (let (split-width-threshold)
+    (apply 'pop-to-buffer args)))
+
 ;; Perform BODY in the summary buffer
 ;; in such a way that its cursor is properly updated in its own window.
 (defmacro rmail-select-summary (&rest body)
@@ -800,7 +819,7 @@ that knows the exact ordering of the \\( \\) subexpressions.")
           (save-excursion
             (unwind-protect
                 (progn
-                  (pop-to-buffer rmail-summary-buffer)
+                  (rmail-pop-to-buffer rmail-summary-buffer)
                   ;; rmail-total-messages is a buffer-local var
                   ;; in the rmail buffer.
                   ;; This way we make it available for the body
@@ -1294,24 +1313,34 @@ Instead, these commands are available:
 (defun rmail-generate-viewer-buffer ()
   "Return a reusable buffer suitable for viewing messages.
 Create the buffer if necessary."
-  (let* ((suffix (file-name-nondirectory (or buffer-file-name (buffer-name))))
-        (name (format " *message-viewer %s*" suffix))
-        (buf (get-buffer name)))
-    (or buf
-       (generate-new-buffer name))))
+  ;; We want to reuse any existing view buffer, so as not to create an
+  ;; endless number of them.  But we must avoid clashes if we visit
+  ;; two different rmail files with the same basename (Bug#4593).
+  (if (and (local-variable-p 'rmail-view-buffer)
+          (buffer-live-p rmail-view-buffer))
+      rmail-view-buffer
+    (generate-new-buffer
+     (format " *message-viewer %s*"
+            (file-name-nondirectory (or buffer-file-name (buffer-name)))))))
 
 (defun rmail-swap-buffers ()
   "Swap text between current buffer and `rmail-view-buffer'.
 This function preserves the current buffer's modified flag, and also
 sets the current buffer's `buffer-file-coding-system' to that of
 `rmail-view-buffer'."
-  (let ((modp (buffer-modified-p))
-       (coding
+  (let ((modp-this (buffer-modified-p))
+       (modp-that
+        (with-current-buffer rmail-view-buffer (buffer-modified-p)))
+       (coding-this buffer-file-coding-system)
+       (coding-that
         (with-current-buffer rmail-view-buffer
           buffer-file-coding-system)))
     (buffer-swap-text rmail-view-buffer)
-    (setq buffer-file-coding-system coding)
-    (restore-buffer-modified-p modp)))
+    (setq buffer-file-coding-system coding-that)
+    (with-current-buffer rmail-view-buffer
+      (setq buffer-file-coding-system coding-this)
+      (restore-buffer-modified-p modp-that))
+    (restore-buffer-modified-p modp-this)))
 
 (defun rmail-buffers-swapped-p ()
   "Return non-nil if the message collection is in `rmail-view-buffer'."
@@ -1367,6 +1396,9 @@ If so restore the actual mbox message collection."
   (set-buffer-multibyte nil)
   (with-current-buffer (setq rmail-view-buffer (rmail-generate-viewer-buffer))
     (setq buffer-undo-list t)
+    ;; Note that this does not erase the buffer.  Should it?
+    ;; It depends on how this is called.  If somehow called with the
+    ;; rmail buffers swapped, it would erase the message collection.
     (set (make-local-variable 'rmail-overlay-list) nil)
     (set-buffer-multibyte t)
     ;; Force C-x C-s write Unix EOLs.
@@ -1477,17 +1509,9 @@ Hook `rmail-quit-hook' is run after expunging."
       (set-buffer-modified-p nil))
     (replace-buffer-in-windows rmail-summary-buffer)
     (bury-buffer rmail-summary-buffer))
-  (if rmail-enable-mime
-      (let ((obuf rmail-buffer)
-           (ovbuf rmail-view-buffer))
-       (set-buffer rmail-view-buffer)
-       (quit-window)
-       (replace-buffer-in-windows ovbuf)
-       (replace-buffer-in-windows obuf)
-       (bury-buffer obuf))
-    (let ((obuf (current-buffer)))
-      (quit-window)
-      (replace-buffer-in-windows obuf))))
+  (let ((obuf (current-buffer)))
+    (quit-window)
+    (replace-buffer-in-windows obuf)))
 
 (defun rmail-bury ()
   "Bury current Rmail buffer and its summary buffer."
@@ -1609,8 +1633,6 @@ The duplicate copy goes into the Rmail file just after the original."
 (declare-function rmail-summary-mark-deleted "rmailsum" (&optional n undel))
 (declare-function rfc822-addresses "rfc822" (header-text))
 (declare-function mail-abbrev-make-syntax-table "mailabbrev.el" ())
-(declare-function mail-sendmail-delimit-header "sendmail" ())
-(declare-function mail-header-end "sendmail" ())
 
 ;; RLK feature not added in this version:
 ;; argument specifies inbox file or files in various ways.
@@ -2189,15 +2211,7 @@ If nil, that means the current message."
   (let ((blurb (rmail-get-labels)))
     (setq mode-line-process
          (format " %d/%d%s"
-                 rmail-current-message rmail-total-messages blurb))
-    ;; If rmail-enable-mime is non-nil, we may have to update
-    ;; `mode-line-process' of rmail-view-buffer too.
-    (if (and rmail-enable-mime
-            (not (eq (current-buffer) rmail-view-buffer))
-            (buffer-live-p rmail-view-buffer))
-       (let ((mlp mode-line-process))
-         (with-current-buffer rmail-view-buffer
-           (setq mode-line-process mlp))))))
+                 rmail-current-message rmail-total-messages blurb))))
 
 (defun rmail-get-attr-value (attr state)
   "Return the character value for ATTR.
@@ -2676,60 +2690,71 @@ The current mail message becomes the message displayed."
          (message "Showing message %d" msg))
        (narrow-to-region beg end)
        (goto-char beg)
-       (setq body-start (search-forward "\n\n" nil t))
-       (narrow-to-region beg (point))
-       (goto-char beg)
-       (save-excursion
-         (if (re-search-forward "^X-Coding-System: *\\(.*\\)$" nil t)
-             (setq coding-system (intern (match-string 1)))
-           (setq coding-system (rmail-get-coding-system))))
-       (setq character-coding (mail-fetch-field "content-transfer-encoding")
-             is-text-message (rmail-is-text-p))
-       (if character-coding
-           (setq character-coding (downcase character-coding)))
-       (narrow-to-region beg end)
-       ;; Decode the message body into an empty view buffer using a
-       ;; unibyte temporary buffer where the character decoding takes
-       ;; place.
        (with-current-buffer rmail-view-buffer
          ;; We give the view buffer a buffer-local value of
          ;; rmail-header-style based on the binding in effect when
          ;; this function is called; `rmail-toggle-headers' can
          ;; inspect this value to determine how to toggle.
-         (set (make-local-variable 'rmail-header-style) header-style)
-         (erase-buffer))
-       (if (null character-coding)
-           ;; Do it directly since that is fast.
-           (rmail-decode-region body-start end coding-system view-buf)
-         ;; Can this be done directly, skipping the temp buffer?
-         (with-temp-buffer
-           (set-buffer-multibyte nil)
-           (insert-buffer-substring mbox-buf body-start end)
-           (cond
-            ((string= character-coding "quoted-printable")
-             (mail-unquote-printable-region (point-min) (point-max)))
-            ((and (string= character-coding "base64") is-text-message)
-             (base64-decode-region (point-min) (point-max)))
-            ((eq character-coding 'uuencode)
-             (error "uuencoded messages are not supported yet"))
-            (t))
-           (rmail-decode-region (point-min) (point-max)
-                                coding-system view-buf)))
-       (with-current-buffer rmail-view-buffer
-         ;; Unquote quoted From lines
-         (goto-char (point-min))
-         (while (re-search-forward "^>+From " nil t)
-           (beginning-of-line)
-           (delete-char 1)
-           (forward-line))
-         (goto-char (point-min)))
-       ;; Copy the headers to the front of the message view buffer.
-       (rmail-copy-headers beg end)
-       ;; Add the separator (blank line) between headers and body;
+         (set (make-local-variable 'rmail-header-style) header-style))
+       (if (and rmail-enable-mime
+                (re-search-forward "mime-version: 1.0" nil t))
+           (let ((rmail-buffer mbox-buf)
+                 (rmail-view-buffer view-buf))
+             (funcall rmail-show-mime-function))
+         (setq body-start (search-forward "\n\n" nil t))
+         (narrow-to-region beg (point))
+         (goto-char beg)
+         (save-excursion
+           (if (re-search-forward "^X-Coding-System: *\\(.*\\)$" nil t)
+               (setq coding-system (intern (match-string 1)))
+             (setq coding-system (rmail-get-coding-system))))
+         (setq character-coding (mail-fetch-field "content-transfer-encoding")
+               is-text-message (rmail-is-text-p))
+         (if character-coding
+             (setq character-coding (downcase character-coding)))
+         (narrow-to-region beg end)
+         ;; Decode the message body into an empty view buffer using a
+         ;; unibyte temporary buffer where the character decoding takes
+         ;; place.
+         (with-current-buffer rmail-view-buffer
+           (erase-buffer))
+         (if (null character-coding)
+             ;; Do it directly since that is fast.
+             (rmail-decode-region body-start end coding-system view-buf)
+           ;; Can this be done directly, skipping the temp buffer?
+           (with-temp-buffer
+             (set-buffer-multibyte nil)
+             (insert-buffer-substring mbox-buf body-start end)
+             (cond
+              ((string= character-coding "quoted-printable")
+               ;; See bug#5441.
+               (or (mail-unquote-printable-region (point-min) (point-max)
+                                                  nil t 'unibyte)
+                   (message "Malformed MIME quoted-printable message")))
+              ((and (string= character-coding "base64") is-text-message)
+               (condition-case err
+                   (base64-decode-region (point-min) (point-max))
+                 (error (message "%s" (cdr err)))))
+              ((eq character-coding 'uuencode)
+               (error "uuencoded messages are not supported yet"))
+              (t))
+             (rmail-decode-region (point-min) (point-max)
+                                  coding-system view-buf)))
+         (with-current-buffer rmail-view-buffer
+           ;; Prepare the separator (blank line) before the body.
+           (goto-char (point-min))
+           (insert "\n")
+           ;; Unquote quoted From lines
+           (while (re-search-forward "^>+From " nil t)
+             (beginning-of-line)
+             (delete-char 1)
+             (forward-line))
+           (goto-char (point-min)))
+         ;; Copy the headers to the front of the message view buffer.
+         (rmail-copy-headers beg end))
        ;; highlight the message, activate any URL like text and add
        ;; special highlighting for and quoted material.
        (with-current-buffer rmail-view-buffer
-         (insert "\n")
          (goto-char (point-min))
          (rmail-highlight-headers)
                                        ;(rmail-activate-urls)
@@ -2860,7 +2885,7 @@ using the coding system CODING."
 
 (defun rmail-highlight-headers ()
   "Highlight the headers specified by `rmail-highlighted-headers'.
-Uses the face `rmail-highlight'."
+Uses the face specified by `rmail-highlight-face'."
   (if rmail-highlighted-headers
       (save-excursion
        (search-forward "\n\n" nil 'move)
@@ -2868,6 +2893,11 @@ Uses the face `rmail-highlight'."
          (narrow-to-region (point-min) (point))
          (let ((case-fold-search t)
                (inhibit-read-only t)
+               ;; When rmail-highlight-face is removed, just
+               ;; use 'rmail-highlight here.
+               (face (or rmail-highlight-face
+                         (if (face-differs-from-default-p 'bold)
+                             'bold 'highlight)))
                ;; List of overlays to reuse.
                (overlays rmail-overlay-list))
            (goto-char (point-min))
@@ -2886,12 +2916,12 @@ Uses the face `rmail-highlight'."
                    (progn
                      (setq overlay (car overlays)
                            overlays (cdr overlays))
-                     (overlay-put overlay 'face 'rmail-highlight)
+                     (overlay-put overlay 'face face)
                      (move-overlay overlay beg (point)))
                  ;; Make a new overlay and add it to
                  ;; rmail-overlay-list.
                  (setq overlay (make-overlay beg (point)))
-                 (overlay-put overlay 'face 'rmail-highlight)
+                 (overlay-put overlay 'face face)
                  (setq rmail-overlay-list
                        (cons overlay rmail-overlay-list))))))))))
 
@@ -3410,30 +3440,62 @@ does not pop any summary buffer."
 ;;;; *** Rmail Mailing Commands ***
 
 (defun rmail-start-mail (&optional noerase to subject in-reply-to cc
-                                  replybuffer sendactions same-window others)
-  (let (yank-action)
+                                  replybuffer sendactions same-window
+                                  other-headers)
+  (let ((switch-function
+        (cond (same-window nil)
+              (rmail-mail-new-frame 'switch-to-buffer-other-frame)
+              (t 'switch-to-buffer-other-window)))
+       yank-action)
     (if replybuffer
        ;; The function used here must behave like insert-buffer wrt
        ;; point and mark (see doc of sc-cite-original).
        (setq yank-action (list 'insert-buffer replybuffer)))
-    (setq others (cons (cons "cc" cc) others))
-    (setq others (cons (cons "in-reply-to" in-reply-to) others))
-    (if same-window
-       (compose-mail to subject others
-                     noerase nil
-                     yank-action sendactions)
-      (if rmail-mail-new-frame
-         (prog1
-             (compose-mail to subject others
-                           noerase 'switch-to-buffer-other-frame
-                           yank-action sendactions)
-           ;; This is not a standard frame parameter;
-           ;; nothing except sendmail.el looks at it.
-           (modify-frame-parameters (selected-frame)
-                                    '((mail-dedicated-frame . t))))
-       (compose-mail to subject others
-                     noerase 'switch-to-buffer-other-window
-                     yank-action sendactions)))))
+    (push (cons "cc" cc) other-headers)
+    (push (cons "in-reply-to" in-reply-to) other-headers)
+    (prog1
+       (compose-mail to subject other-headers noerase
+                     switch-function yank-action sendactions
+                     '(rmail-mail-return))
+      (if (eq switch-function 'switch-to-buffer-other-frame)
+         ;; This is not a standard frame parameter; nothing except
+         ;; sendmail.el looks at it.
+         (modify-frame-parameters (selected-frame)
+                                  '((mail-dedicated-frame . t)))))))
+
+(defun rmail-mail-return ()
+  (cond
+   ;; If there is only one visible frame with no special handling,
+   ;; consider deleting the mail window to return to Rmail.
+   ((or (null (delq (selected-frame) (visible-frame-list)))
+       (not (or (window-dedicated-p (frame-selected-window))
+                (and pop-up-frames (one-window-p))
+                (cdr (assq 'mail-dedicated-frame
+                           (frame-parameters))))))
+    (let (rmail-flag summary-buffer)
+      (and (not (one-window-p))
+          (with-current-buffer
+              (window-buffer (next-window (selected-window) 'not))
+            (setq rmail-flag (eq major-mode 'rmail-mode))
+            (setq summary-buffer
+                  (and (boundp 'mail-bury-selects-summary)
+                       mail-bury-selects-summary
+                       (boundp 'rmail-summary-buffer)
+                       rmail-summary-buffer
+                       (buffer-name rmail-summary-buffer)
+                       (not (get-buffer-window rmail-summary-buffer))
+                       rmail-summary-buffer))))
+      (if rmail-flag
+         ;; If the Rmail buffer has a summary, show that.
+         (if summary-buffer (switch-to-buffer summary-buffer)
+           (delete-window)))))
+   ;; If the frame was probably made for this buffer, the user
+   ;; probably wants to delete it now.
+   ((display-multi-frame-p)
+    (delete-frame (selected-frame)))
+   ;; The previous frame is where normally they have the Rmail buffer
+   ;; displayed.
+   (t (other-frame -1))))
 
 (defun rmail-mail ()
   "Send mail in another window.
@@ -3644,7 +3706,8 @@ see the documentation of `rmail-resend'."
          ;; The mail buffer is now current.
          (save-excursion
            ;; Insert after header separator--before signature if any.
-           (goto-char (mail-text-start))
+           (rfc822-goto-eoh)
+           (forward-line 1)
            (if (or rmail-enable-mime rmail-enable-mime-composing)
                (funcall rmail-insert-mime-forwarded-message-function
                         forward-buffer)
@@ -3799,6 +3862,8 @@ The message should be narrowed to just the headers."
                           (1- (point))
                         (point-max)))))))
 
+(autoload 'mail-position-on-field "sendmail")
+
 (defun rmail-retry-failure ()
   "Edit a mail message which is based on the contents of the current message.
 For a message rejected by the mail system, extract the interesting headers and
@@ -3883,16 +3948,19 @@ specifying headers which should not be copied into the new message."
          ;; Insert original text as initial text of new draft message.
          ;; Bind inhibit-read-only since the header delimiter
          ;; of the previous message was probably read-only.
-         (let ((inhibit-read-only t))
+         (let ((inhibit-read-only t)
+               eoh)
            (erase-buffer)
            (insert-buffer-substring rmail-this-buffer
                                     bounce-start bounce-end)
            (goto-char (point-min))
            (if bounce-indent
                (indent-rigidly (point-min) (point-max) bounce-indent))
-           (mail-sendmail-delimit-header)
+           (rfc822-goto-eoh)
+           (setq eoh (point))
+           (insert mail-header-separator)
            (save-restriction
-             (narrow-to-region (point-min) (mail-header-end))
+             (narrow-to-region (point-min) eoh)
              (rmail-delete-headers rmail-retry-ignored-headers)
              (rmail-delete-headers "^\\(sender\\|return-path\\|received\\):")
              (setq resending (mail-fetch-field "resent-to"))
@@ -4165,18 +4233,36 @@ encoded string (and the same mask) will decode the string."
 (add-to-list 'desktop-buffer-mode-handlers
             '(rmail-mode . rmail-restore-desktop-buffer))
 
+;; We use this to record the encoding of the current message before
+;; saving the message collection.
+(defvar rmail-message-encoding nil)
+
 ;; Used in `write-region-annotate-functions' to write rmail files.
 (defun rmail-write-region-annotate (start end)
   (when (and (null start) (rmail-buffers-swapped-p))
+    (setq rmail-message-encoding buffer-file-coding-system)
     (set-buffer rmail-view-buffer)
     (widen)
     nil))
 
+;; Used to restore the encoding of the buffer where we show the
+;; current message, after we save the message collection.  This is
+;; needed because rmail-write-region-annotate switches buffers behind
+;; save-file's back, with the side effect that last-coding-system-used
+;; is assigned to buffer-file-coding-system of the wrong buffer.
+(defun rmail-after-save-hook ()
+  (if (or (eq rmail-view-buffer (current-buffer))
+         (eq rmail-buffer (current-buffer)))
+      (with-current-buffer
+         (if (rmail-buffers-swapped-p) rmail-buffer rmail-view-buffer)
+       (setq buffer-file-coding-system rmail-message-encoding))))
+(add-hook 'after-save-hook 'rmail-after-save-hook)
+
 \f
 ;;; Start of automatically extracted autoloads.
 \f
 ;;;### (autoloads (rmail-edit-current-message) "rmailedit" "rmailedit.el"
-;;;;;;  "c70c6c35b8c5bbdb73787a48b83e5adc")
+;;;;;;  "1602595714ff15197cf32727d6765c31")
 ;;; Generated autoloads from rmailedit.el
 
 (autoload 'rmail-edit-current-message "rmailedit" "\
@@ -4188,7 +4274,7 @@ Edit the contents of this message.
 \f
 ;;;### (autoloads (rmail-next-labeled-message rmail-previous-labeled-message
 ;;;;;;  rmail-read-label rmail-kill-label rmail-add-label) "rmailkwd"
-;;;;;;  "rmailkwd.el" "2e986921026eea971b49e91f53967f77")
+;;;;;;  "rmailkwd.el" "061943b8a3dfd5695715b36736827950")
 ;;; Generated autoloads from rmailkwd.el
 
 (autoload 'rmail-add-label "rmailkwd" "\
@@ -4231,23 +4317,33 @@ With prefix argument N moves forward N messages with these labels.
 
 ;;;***
 \f
-;;;### (autoloads (rmail-mime) "rmailmm" "rmailmm.el" "ab34439779d8036dbd5cdc80fb4cea64")
+;;;### (autoloads (rmail-mime) "rmailmm" "rmailmm.el" "783deb7c855767051af119f1bfd8d84e")
 ;;; Generated autoloads from rmailmm.el
 
 (autoload 'rmail-mime "rmailmm" "\
-Process the current Rmail message as a MIME message.
-This creates a temporary \"*RMAIL*\" buffer holding a decoded
-copy of the message.  Inline content-types are handled according to
+Toggle displaying of a MIME message.
+
+The actualy behavior depends on the value of `rmail-enable-mime'.
+
+If `rmail-enable-mime' is t (default), this command change the
+displaying of a MIME message between decoded presentation form
+and raw data.
+
+With ARG, toggle the displaying of the current MIME entity only.
+
+If `rmail-enable-mime' is nil, this creates a temporary
+\"*RMAIL*\" buffer holding a decoded copy of the message.  Inline
+content-types are handled according to
 `rmail-mime-media-type-handlers-alist'.  By default, this
 displays text and multipart messages, and offers to download
 attachments as specfied by `rmail-mime-attachment-dirs-alist'.
 
-\(fn)" t nil)
+\(fn &optional ARG)" t nil)
 
 ;;;***
 \f
 ;;;### (autoloads (set-rmail-inbox-list) "rmailmsc" "rmailmsc.el"
-;;;;;;  "de01c37c81339201034a01732b97f44e")
+;;;;;;  "f1d9be06745c78b90224da788f61c2d9")
 ;;; Generated autoloads from rmailmsc.el
 
 (autoload 'set-rmail-inbox-list "rmailmsc" "\
@@ -4263,7 +4359,7 @@ This applies only to the current session.
 \f
 ;;;### (autoloads (rmail-sort-by-labels rmail-sort-by-lines rmail-sort-by-correspondent
 ;;;;;;  rmail-sort-by-recipient rmail-sort-by-author rmail-sort-by-subject
-;;;;;;  rmail-sort-by-date) "rmailsort" "rmailsort.el" "3f2b10b0272ea56cb604f29330d95fc4")
+;;;;;;  rmail-sort-by-date) "rmailsort" "rmailsort.el" "8b20167ea495d683f83f980833e948e0")
 ;;; Generated autoloads from rmailsort.el
 
 (autoload 'rmail-sort-by-date "rmailsort" "\
@@ -4322,7 +4418,7 @@ If prefix argument REVERSE is non-nil, sorts in reverse order.
 \f
 ;;;### (autoloads (rmail-summary-by-senders rmail-summary-by-topic
 ;;;;;;  rmail-summary-by-regexp rmail-summary-by-recipients rmail-summary-by-labels
-;;;;;;  rmail-summary) "rmailsum" "rmailsum.el" "60bec0ae88b7ed18dd6845ddb9ccd904")
+;;;;;;  rmail-summary) "rmailsum" "rmailsum.el" "b1d2ca7470a7d8baffe9e90a15a5b5e0")
 ;;; Generated autoloads from rmailsum.el
 
 (autoload 'rmail-summary "rmailsum" "\
@@ -4370,7 +4466,7 @@ SENDERS is a string of regexps separated by commas.
 ;;;***
 \f
 ;;;### (autoloads (unforward-rmail-message undigestify-rmail-message)
-;;;;;;  "undigest" "undigest.el" "b691540ddff5c394e9ebc3517051445f")
+;;;;;;  "undigest" "undigest.el" "1b5181e02606e49ede71604472250cc3")
 ;;; Generated autoloads from undigest.el
 
 (autoload 'undigestify-rmail-message "undigest" "\
@@ -4393,5 +4489,4 @@ following the containing message.
 
 (provide 'rmail)
 
-;; arch-tag: 65d257d3-c281-4a65-9c38-e61af95af2f0
 ;;; rmail.el ends here