(mime-edit-normalize-body): Don't use the `(replace-match "\\1\r\n")' form
[elisp/semi.git] / mime-edit.el
index 56ed41f..18263bf 100644 (file)
@@ -1,16 +1,16 @@
 ;;; mime-edit.el --- Simple MIME Composer for GNU Emacs
 
-;; Copyright (C) 1993,1994,1995,1996,1997 Free Software Foundation, Inc.
+;; Copyright (C) 1993,94,95,96,97,98,99,2000,01,02,03
+;;   Free Software Foundation, Inc.
 
 ;; Author: UMEDA Masanobu <umerin@mse.kyutech.ac.jp>
-;;         MORIOKA Tomohiko <morioka@jaist.ac.jp>
-;; Maintainer: MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;;     MORIOKA Tomohiko <tomo@kanji.zinbun.kyoto-u.ac.jp>
+;;     Daiki Ueno <ueno@ueda.info.waseda.ac.jp>
 ;; Created: 1994/08/21 renamed from mime.el
 ;;     Renamed: 1997/2/21 from tm-edit.el
-;; Version: $Revision: 0.57 $
 ;; Keywords: MIME, multimedia, multilingual, mail, news
 
-;; This file is part of SEMI (SEMI is Emacs MIME Interfaces).
+;; This file is part of SEMI (Sophisticated Emacs MIME Interfaces).
 
 ;; This program is free software; you can redistribute it and/or
 ;; modify it under the terms of the GNU General Public License as
 ;; composed in the tagged MIME format are automatically translated
 ;; into a MIME compliant message when exiting the mode.
 
-;; Mule (a multilingual extension to Emacs 18 and 19) has a capability
-;; of handling multilingual text in limited ISO-2022 manner that is
-;; based on early experiences in Japanese Internet community and
-;; resulted in RFC 1468 (ISO-2022-JP charset for MIME).  In order to
-;; enable multilingual capability in single text message in MIME,
-;; charset of multilingual text written in Mule is declared as either
-;; `ISO-2022-JP-2' [RFC 1554].  Mule is required for reading the such
-;; messages.
+;; Mule (multilingual feature of Emacs 20 and multilingual extension
+;; for XEmacs 20) has a capability of handling multilingual text in
+;; limited ISO-2022 manner that is based on early experiences in
+;; Japanese Internet community and resulted in RFC 1468 (ISO-2022-JP
+;; charset for MIME).  In order to enable multilingual capability in
+;; single text message in MIME, charset of multilingual text written
+;; in Mule is declared as either `ISO-2022-JP-2' [RFC 1554].  Mule is
+;; required for reading the such messages.
 
 ;; This MIME composer can work with Mail mode, mh-e letter Mode, and
 ;; News mode.  First of all, you need the following autoload
 ;; definition to load mime-edit-mode automatically:
 ;;
-;; (autoload 'mime-edit-mode "mime-edit"
+;; (autoload 'turn-on-mime-edit "mime-edit"
 ;;           "Minor mode for editing MIME message." t)
 ;;
 ;; In case of Mail mode (includes VM mode), you need the following
 ;; hook definition:
 ;;
-;; (add-hook 'mail-mode-hook 'mime-edit-mode)
+;; (add-hook 'mail-mode-hook 'turn-on-mime-edit)
 ;; (add-hook 'mail-send-hook 'mime-edit-maybe-translate)
 ;;
 ;; In case of MH-E, you need the following hook definition:
@@ -63,7 +63,7 @@
 ;; (add-hook 'mh-letter-mode-hook
 ;;           (function
 ;;            (lambda ()
-;;              (mime-edit-mode)
+;;              (turn-on-mime-edit)
 ;;              (make-local-variable 'mail-header-separator)
 ;;              (setq mail-header-separator "--------")
 ;;              ))))
@@ -71,7 +71,7 @@
 ;;
 ;; In case of News mode, you need the following hook definition:
 ;;
-;; (add-hook 'news-reply-mode-hook 'mime-edit-mode)
+;; (add-hook 'news-reply-mode-hook 'turn-on-mime-edit)
 ;; (add-hook 'news-inews-hook 'mime-edit-maybe-translate)
 ;;
 ;; In case of Emacs 19, it is possible to emphasize the message tags
@@ -92,7 +92,7 @@
 ;;
 ;; This is a conventional plain text.  It should be translated into
 ;; text/plain.
-;; 
+;;
 ;;--[[text/plain]]
 ;; This is also a plain text.  But, it is explicitly specified as is.
 ;;--[[text/plain; charset=ISO-8859-1]]
 
 ;;; Code:
 
-(require 'emu)
 (require 'sendmail)
 (require 'mail-utils)
 (require 'mel)
 (require 'mime-view)
-(require 'eword-encode)
 (require 'signature)
 (require 'alist)
+(require 'invisible)
+(require 'pgg-def)
+(require 'pgg-parse)
+
+(autoload 'pgg-encrypt-region "pgg"
+  "PGP encryption of current region." t)
+(autoload 'pgg-sign-region "pgg"
+  "PGP signature of current region." t)
+(autoload 'pgg-insert-key "pgg"
+  "Insert PGP public key at point." t)
+(autoload 'smime-encrypt-region "smime"
+  "S/MIME encryption of current region.")
+(autoload 'smime-sign-region "smime"
+  "S/MIME signature of current region.")
+(defvar smime-output-buffer)
+(defvar smime-errors-buffer)
 
 
 ;;; @ version
 ;;;
 
-(defconst mime-edit-RCS-ID
-  "$Id: mime-edit.el,v 0.57 1997-03-04 12:34:50 morioka Exp $")
-
-(defconst mime-edit-version (get-version-string mime-edit-RCS-ID))
-
-(defconst mime-edit-version-name
-  (concat "SEMI MIME-Edit " mime-edit-version))
+(eval-and-compile
+  (defconst mime-edit-version
+    (concat
+     (mime-product-name mime-user-interface-product) " "
+     (mapconcat #'number-to-string
+               (mime-product-version mime-user-interface-product) ".")
+     " - \"" (mime-product-code-name mime-user-interface-product) "\"")))
 
 
 ;;; @ variables
 ;;;
 
-(defvar mime-prefix "\C-c\C-x"
-  "*Keymap prefix for MIME commands.")
+(defgroup mime-edit nil
+  "MIME edit mode"
+  :group 'mime)
 
-(defvar mime-ignore-preceding-spaces nil
-  "*Ignore preceding white spaces if non-nil.")
+(defcustom mime-ignore-preceding-spaces nil
+  "*Ignore preceding white spaces if non-nil."
+  :group 'mime-edit
+  :type 'boolean)
 
-(defvar mime-ignore-trailing-spaces nil
-  "*Ignore trailing white spaces if non-nil.")
+(defcustom mime-ignore-trailing-spaces nil
+  "*Ignore trailing white spaces if non-nil."
+  :group 'mime-edit
+  :type 'boolean)
 
-(defvar mime-ignore-same-text-tag t
+(defcustom mime-ignore-same-text-tag t
   "*Ignore preceding text content-type tag that is same with new one.
-If non-nil, the text tag is not inserted unless something different.")
+If non-nil, the text tag is not inserted unless something different."
+  :group 'mime-edit
+  :type 'boolean)
 
-(defvar mime-auto-hide-body t
-  "*Hide non-textual body encoded in base64 after insertion if non-nil.")
+(defcustom mime-auto-hide-body t
+  "*Hide non-textual body encoded in base64 after insertion if non-nil."
+  :group 'mime-edit
+  :type 'boolean)
 
-(defvar mime-edit-voice-recorder
+(defcustom mime-edit-voice-recorder
   (function mime-edit-voice-recorder-for-sun)
-  "*Function to record a voice message and encode it. [mime-edit.el]")
+  "*Function to record a voice message and encode it."
+  :group 'mime-edit
+  :type 'function)
 
-(defvar mime-edit-mode-hook nil
-  "*Hook called when enter MIME mode.")
+(defcustom mime-edit-mode-hook nil
+  "*Hook called when enter MIME mode."
+  :group 'mime-edit
+  :type 'hook)
 
-(defvar mime-edit-translate-hook nil
+(defcustom mime-edit-translate-hook nil
   "*Hook called before translating into a MIME compliant message.
 To insert a signature file automatically, call the function
-`mime-edit-insert-signature' from this hook.")
+`mime-edit-insert-signature' from this hook."
+  :group 'mime-edit
+  :type 'hook)
 
-(defvar mime-edit-exit-hook nil
-  "*Hook called when exit MIME mode.")
+(defcustom mime-edit-exit-hook nil
+  "*Hook called when exit MIME mode."
+  :group 'mime-edit
+  :type 'hook)
 
 (defvar mime-content-types
   '(("text"
@@ -171,19 +202,12 @@ To insert a signature file automatically, call the function
      ("plain"
       ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8")
       )
-     ("richtext"
-      ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8")
-      )
-     ("enriched"
-      ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8")
-      )
-     ("x-latex"
-      ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8")
-      )
-     ("html"
-      ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8")
-      )
-     ("x-rot13-47")
+     ("enriched")
+     ("html")
+     ("css") ; rfc2318
+     ("xml") ; rfc2376
+     ("x-latex")
+     ;; ("x-rot13-47-48")
      )
     ("message"
      ("external-body"
@@ -201,17 +225,23 @@ To insert a signature file automatically, call the function
        ("tftp"        ("site") ("name"))
        ("afs"         ("site") ("name"))
        ("local-file"  ("site") ("name"))
-       ("mail-server" ("server" "ftpmail@nic.karrn.ad.jp"))
+       ("mail-server"
+       ("server" "ftpmail@nic.karrn.ad.jp")
+       ("subject"))
+       ("url"         ("url"))
        ))
      ("rfc822")
+     ("news")
      )
     ("application"
      ("octet-stream" ("type" "" "tar" "shar"))
      ("postscript")
+     ("vnd.ms-powerpoint")
      ("x-kiss" ("x-cnf")))
     ("image"
      ("gif")
      ("jpeg")
+     ("png")
      ("tiff")
      ("x-pic")
      ("x-mag")
@@ -223,21 +253,94 @@ To insert a signature file automatically, call the function
     )
   "*Alist of content-type, subtype, parameters and its values.")
 
-(defvar mime-file-types
-  '(("\\.rtf$"
-     "text"    "richtext"      nil
+(defcustom mime-file-types
+  '(
+
+    ;; Programming languages
+
+    ("\\.cc$"
+     "application" "octet-stream" (("type" . "C++"))
+     "7bit"
+     "attachment"      (("filename" . file))
+     )
+
+    ("\\.el$"
+     "application" "octet-stream" (("type" . "emacs-lisp"))
+     "7bit"
+     "attachment"      (("filename" . file))
+     )
+
+    ("\\.lsp$"
+     "application" "octet-stream" (("type" . "common-lisp"))
+     "7bit"
+     "attachment"      (("filename" . file))
+     )
+
+    ("\\.pl$"
+     "application" "octet-stream" (("type" . "perl"))
+     "7bit"
+     "attachment"      (("filename" . file))
+     )
+
+    ;; Text or translated text
+
+    ("\\.txt$"
+     "text"    "plain"         nil
      nil
-     nil               nil)
+     "inline"          (("filename" . file))
+     )
+
+     ;; .rc : procmail modules pm-xxxx.rc
+     ;; *rc : other resource files
+
+    ("\\.\\(rc\\|lst\\|log\\|sql\\|mak\\)$\\|\\..*rc$"
+     "text"    "plain"         nil
+     nil
+     "attachment"      (("filename" . file))
+     )
+
     ("\\.html$"
      "text"    "html"          nil
      nil
      nil               nil)
+
+    ("\\.diff$\\|\\.patch$"
+     "application" "octet-stream" (("type" . "patch"))
+     nil
+     "attachment"      (("filename" . file))
+     )
+
+    ("\\.signature"
+     "text"    "plain"         nil     nil     nil     nil)
+
+
+    ;;  Octect binary text
+
+    ("\\.doc$"                         ;MS Word
+     "application" "msword" nil
+     "base64"
+     "attachment" (("filename" . file))
+     )
+    ("\\.ppt$"                         ; MS Power Point
+     "application" "vnd.ms-powerpoint" nil
+     "base64"
+     "attachment" (("filename" . file))
+     )
+
+    ("\\.pln$"
+     "text"    "plain"         nil
+     nil
+     "inline"          (("filename" . file))
+     )
     ("\\.ps$"
      "application" "postscript"        nil
      "quoted-printable"
      "attachment"      (("filename" . file))
      )
-    ("\\.jpg$"
+
+    ;;  Pure binary
+
+    ("\\.jpg$\\|\\.jpeg$"
      "image"   "jpeg"          nil
      "base64"
      "inline"          (("filename" . file))
@@ -247,6 +350,11 @@ To insert a signature file automatically, call the function
      "base64"
      "inline"          (("filename" . file))
      )
+    ("\\.png$"
+     "image"   "png"           nil
+     "base64"
+     "inline"          (("filename" . file))
+     )
     ("\\.tiff$"
      "image"   "tiff"          nil
      "base64"
@@ -282,16 +390,6 @@ To insert a signature file automatically, call the function
      "base64"
      "attachment"      (("filename" . file))
      )
-    ("\\.el$"
-     "application" "octet-stream" (("type" . "emacs-lisp"))
-     "7bit"
-     "attachment"      (("filename" . file))
-     )
-    ("\\.lsp$"
-     "application" "octet-stream" (("type" . "common-lisp"))
-     "7bit"
-     "attachment"      (("filename" . file))
-     )
     ("\\.tar\\.gz$"
      "application" "octet-stream" (("type" . "tar+gzip"))
      "base64"
@@ -332,26 +430,58 @@ To insert a signature file automatically, call the function
      "base64"
      "attachment"      (("filename" . file))
      )
-    ("\\.diff$"
-     "application" "octet-stream" (("type" . "patch"))
-     nil
-     "attachment"      (("filename" . file))
-     )
-    ("\\.patch$"
-     "application" "octet-stream" (("type" . "patch"))
-     nil
-     "attachment"      (("filename" . file))
-     )
-    ("\\.signature"
-     "text"    "plain"         nil     nil)
+
+    ;; Rest
+
     (".*"
      "application" "octet-stream" nil
      nil
-     "attachment"      (("filename" . file))
-     )
+     "attachment"      (("filename" . file)))
     )
   "*Alist of file name, types, parameters, and default encoding.
-If encoding is nil, it is determined from its contents.")
+If encoding is nil, it is determined from its contents."
+  :type `(repeat
+         (list regexp
+               ;; primary-type
+               (choice :tag "Primary-Type"
+                       ,@(nconc (mapcar (lambda (cell)
+                                          (list 'item (car cell))
+                                          )
+                                        mime-content-types)
+                                '(string)))
+               ;; subtype
+               (choice :tag "Sub-Type"
+                       ,@(nconc
+                          (apply #'nconc
+                                 (mapcar (lambda (cell)
+                                           (mapcar (lambda (cell)
+                                                     (list 'item (car cell))
+                                                     )
+                                                   (cdr cell)))
+                                         mime-content-types))
+                          '(string)))
+               ;; parameters
+               (repeat :tag "Parameters of Content-Type field"
+                       (cons string (choice string symbol)))
+               ;; content-transfer-encoding
+               (choice :tag "Encoding"
+                       ,@(cons
+                          '(const nil)
+                          (mapcar (lambda (cell)
+                                    (list 'item cell)
+                                    )
+                                  (mime-encoding-list))))
+               ;; disposition-type
+               (choice :tag "Disposition-Type"
+                       (item nil)
+                       (item "inline")
+                       (item "attachment")
+                       string)
+               ;; parameters
+               (repeat :tag "Parameters of Content-Disposition field"
+                       (cons string (choice string symbol)))
+               ))
+  :group 'mime-edit)
 
 
 ;;; @@ about charset, encoding and transfer-level
@@ -368,11 +498,18 @@ If encoding is nil, it is determined from its contents.")
     (iso-8859-7                8 "quoted-printable")
     (iso-8859-8                8 "quoted-printable")
     (iso-8859-9                8 "quoted-printable")
+    (iso-8859-14       8 "quoted-printable")
+    (iso-8859-15       8 "quoted-printable")
     (iso-2022-jp       7 "base64")
+    (iso-2022-jp-3     7 "base64")
     (iso-2022-kr       7 "base64")
     (euc-kr            8 "base64")
-    (gb2312            8 "quoted-printable")
+    (cn-gb             8 "base64")
+    (gb2312            8 "base64")
+    (cn-big5           8 "base64")
     (big5              8 "base64")
+    (shift_jis         8 "base64")
+    (tis-620           8 "base64")
     (iso-2022-jp-2     7 "base64")
     (iso-2022-int-1    7 "base64")
     ))
@@ -392,23 +529,10 @@ If encoding is nil, it is determined from its contents.")
   "A string formatted version of mime-transfer-level")
 (make-variable-buffer-local 'mime-transfer-level-string)
 
-(defun mime-make-charset-default-encoding-alist (transfer-level)
-  (mapcar (function
-          (lambda (charset-type)
-            (let ((charset  (car charset-type))
-                  (type     (nth 1 charset-type))
-                  (encoding (nth 2 charset-type))
-                  )
-              (if (<= type transfer-level)
-                  (cons charset (mime-encoding-name type))
-                (cons charset encoding)
-                ))))
-         mime-charset-type-list))
-
-(defvar mime-edit-charset-default-encoding-alist
-  (mime-make-charset-default-encoding-alist mime-transfer-level))
-(make-variable-buffer-local 'mime-edit-charset-default-encoding-alist)
+;;; @@ about content transfer encoding
 
+(defvar mime-content-transfer-encoding-priority-list
+  '(nil "8bit" "binary"))
 
 ;;; @@ about message inserting
 ;;;
@@ -418,7 +542,7 @@ If encoding is nil, it is determined from its contents.")
     "Xref" "X-UIDL" "X-Filter" "X-Gnus-.*" "X-VM-.*")
   "Delete these fields from original message when it is inserted
 as message/rfc822 part.
-Each elements are regexp of field-name. [mime-edit.el]")
+Each elements are regexp of field-name.")
 
 (defvar mime-edit-yank-ignored-field-regexp
   (concat "^"
@@ -432,39 +556,38 @@ Each elements are regexp of field-name. [mime-edit.el]")
 ;;; @@ about message splitting
 ;;;
 
-(defvar mime-edit-split-message t
-  "*Split large message if it is non-nil. [mime-edit.el]")
+(defcustom mime-edit-split-message t
+  "*Split large message if it is non-nil."
+  :group 'mime-edit
+  :type 'boolean)
 
-(defvar mime-edit-message-default-max-lines 1000
-  "*Default maximum lines of a message. [mime-edit.el]")
+(defcustom mime-edit-message-default-max-lines 1000
+  "*Default maximum lines of a message."
+  :group 'mime-edit
+  :type 'integer)
 
-(defvar mime-edit-message-max-lines-alist
+(defcustom mime-edit-message-max-lines-alist
   '((news-reply-mode . 500))
   "Alist of major-mode vs maximum lines of a message.
 If it is not specified for a major-mode,
-`mime-edit-message-default-max-lines' is used. [mime-edit.el]")
+`mime-edit-message-default-max-lines' is used."
+  :group 'mime-edit
+  :type 'list)
 
 (defconst mime-edit-split-ignored-field-regexp
-  "\\(^Content-\\|^Subject:\\|^Mime-Version:\\)")
+  "\\(^Content-\\|^Subject:\\|^Mime-Version:\\|^Message-Id:\\)")
 
-(defvar mime-edit-split-blind-field-regexp
-  "\\(^[BDFbdf]cc:\\|^cc:[ \t]*$\\)")
+(defcustom mime-edit-split-blind-field-regexp
+  "\\(^[BDFbdf]cc:\\|^cc:[ \t]*$\\)"
+  "*Regular expression to match field-name to be ignored when split sending."
+  :group 'mime-edit
+  :type 'regexp)
 
 (defvar mime-edit-split-message-sender-alist nil)
 
 (defvar mime-edit-news-reply-mode-server-running nil)
 
 
-;;; @@ about PGP
-;;;
-
-(defvar mime-edit-signing-type 'pgp-elkins
-  "*PGP signing type (pgp-elkins, pgp-kazu or nil). [mime-edit.el]")
-
-(defvar mime-edit-encrypting-type 'pgp-elkins
-  "*PGP encrypting type (pgp-elkins, pgp-kazu or nil). [mime-edit.el]")
-
-
 ;;; @@ about tag
 ;;;
 
@@ -509,21 +632,82 @@ If it is not specified for a major-mode,
 ;;; @@ optional header fields
 ;;;
 
-(defvar mime-edit-insert-x-emacs-field t
-  "*If non-nil, insert X-Emacs header field.")
-
-(defvar mime-edit-x-emacs-value
-  (if running-xemacs
-      (concat emacs-version
+(defvar mime-edit-insert-user-agent-field t
+  "*If non-nil, insert User-Agent header field.")
+
+(defvar mime-edit-user-agent-value
+  (concat (mime-product-name mime-user-interface-product)
+         "/"
+         (mapconcat #'number-to-string
+                    (mime-product-version mime-user-interface-product) ".")
+         " ("
+         (mime-product-code-name mime-user-interface-product)
+         ") "
+         (mime-product-name mime-library-product)
+         "/"
+         (mapconcat #'number-to-string
+                    (mime-product-version mime-library-product) ".")
+         " ("
+         (mime-product-code-name mime-library-product)
+         ") "
+         (if (fboundp 'apel-version)
+             (concat (apel-version) " "))
+         (if (featurep 'xemacs)
+             (concat (cond ((and (featurep 'chise)
+                                 (boundp 'xemacs-chise-version))
+                            (concat "CHISE-MULE/" xemacs-chise-version))
+                           ((featurep 'utf-2000)
+                            (concat "UTF-2000-MULE/" utf-2000-version))
+                           ((featurep 'mule) "MULE"))
+                     " XEmacs"
+                     (if (string-match "^[0-9]+\\(\\.[0-9]+\\)" emacs-version)
+                         (concat
+                          "/"
+                          (substring emacs-version 0 (match-end 0))
+                          (cond ((and (boundp 'xemacs-betaname)
+                                      xemacs-betaname)
+                                 ;; It does not exist in XEmacs
+                                 ;; versions prior to 20.3.
+                                 (concat " " xemacs-betaname))
+                                ((and (boundp 'emacs-patch-level)
+                                      emacs-patch-level)
+                                 ;; It does not exist in FSF Emacs or in
+                                 ;; XEmacs versions earlier than 21.1.1.
+                                 (format " (patch %d)" emacs-patch-level))
+                                (t ""))
+                          " (" xemacs-codename ")"
+                          ;; `xemacs-extra-name' has appeared in the
+                          ;; development version of XEmacs 21.5-b8.
+                          (if (and (boundp 'xemacs-extra-name)
+                                   (symbol-value 'xemacs-extra-name))
+                              (concat " " (symbol-value 'xemacs-extra-name))
+                            "")
+                          " ("
+                          system-configuration ")")
+                       " (" emacs-version ")"))
+           (let ((ver (if (string-match "\\.[0-9]+$" emacs-version)
+                          (substring emacs-version 0 (match-beginning 0))
+                        emacs-version)))
              (if (featurep 'mule)
-                 " with mule"
-               " without mule"))
-    (let ((ver (if (string-match "\\.[0-9]+$" emacs-version)
-                  (substring emacs-version 0 (match-beginning 0))
-                emacs-version)))
-      (if (featurep 'mule)
-         (concat "Emacs " ver ", MULE " mule-version)
-       ver))))
+                 (if (boundp 'enable-multibyte-characters)
+                     (concat "Emacs/" ver
+                             " (" system-configuration ")"
+                             (if enable-multibyte-characters
+                                 (concat " MULE/" mule-version)
+                               " (with unibyte mode)")
+                             (if (featurep 'meadow)
+                                 (let ((mver (Meadow-version)))
+                                   (if (string-match "^Meadow-" mver)
+                                       (concat " Meadow/"
+                                               (substring mver
+                                                          (match-end 0)))
+                                     ))))
+                   (concat "MULE/" mule-version
+                           " (based on Emacs " ver ")"))
+               (concat "Emacs/" ver " (" system-configuration ")")))))
+  "Body of User-Agent field.
+If variable `mime-edit-insert-user-agent-field' is not nil, it is
+inserted into message header.")
 
 \f
 ;;; @ constants
@@ -534,11 +718,15 @@ If it is not specified for a major-mode,
 Tspecials means any character that matches with it in header must be quoted.")
 
 (defconst mime-edit-mime-version-value
-  (concat "1.0 (generated by " mime-edit-version-name ")")
+  (concat "1.0 (generated by " mime-edit-version ")")
   "MIME version number.")
 
-(defconst mime-edit-mime-map (make-sparse-keymap)
-  "Keymap for MIME commands.")
+(defconst mime-edit-mime-version-field-for-message/partial
+  (concat "MIME-Version:"
+         (mime-encode-field-body
+          (concat " 1.0 (split by " mime-edit-version ")\n")
+          "MIME-Version:"))
+  "MIME version field for message/partial.")
 
 
 ;;; @ keymap and menu
@@ -547,66 +735,59 @@ Tspecials means any character that matches with it in header must be quoted.")
 (defvar mime-edit-mode-flag nil)
 (make-variable-buffer-local 'mime-edit-mode-flag)
 
-(defun mime-edit-define-keymap (keymap)
-  "Add mime-editor commands to KEYMAP."
-  (if (not (keymapp keymap))
-      nil
-    (define-key keymap "\C-t" 'mime-edit-insert-text)
-    (define-key keymap "\C-i" 'mime-edit-insert-file)
-    (define-key keymap "\C-e" 'mime-edit-insert-external)
-    (define-key keymap "\C-v" 'mime-edit-insert-voice)
-    (define-key keymap "\C-y" 'mime-edit-insert-message)
-    (define-key keymap "\C-m" 'mime-edit-insert-mail)
-    (define-key keymap "\C-w" 'mime-edit-insert-signature)
-    (define-key keymap "\C-s" 'mime-edit-insert-signature)
-    (define-key keymap "\C-k" 'mime-edit-insert-key)
-    (define-key keymap "t"    'mime-edit-insert-tag)
-    (define-key keymap "a"    'mime-edit-enclose-alternative-region)
-    (define-key keymap "p"    'mime-edit-enclose-parallel-region)
-    (define-key keymap "m"    'mime-edit-enclose-mixed-region)
-    (define-key keymap "d"    'mime-edit-enclose-digest-region)
-    (define-key keymap "s"    'mime-edit-enclose-signed-region)
-    (define-key keymap "e"    'mime-edit-enclose-encrypted-region)
-    (define-key keymap "q"    'mime-edit-enclose-quote-region)
-    (define-key keymap "7"    'mime-edit-set-transfer-level-7bit)
-    (define-key keymap "8"    'mime-edit-set-transfer-level-8bit)
-    (define-key keymap "/"    'mime-edit-set-split)
-    (define-key keymap "v"    'mime-edit-set-sign)
-    (define-key keymap "h"    'mime-edit-set-encrypt)
-    (define-key keymap "\C-p" 'mime-edit-preview-message)
-    (define-key keymap "\C-z" 'mime-edit-exit)
-    (define-key keymap "?"    'mime-edit-help)
-    ))
-
-(mime-edit-define-keymap mime-edit-mime-map)
-
-(defun mime-edit-toggle-mode ()
-  (interactive)
-  (if mime-edit-mode-flag
-      (mime-edit-exit 'nomime)
-    (mime-edit-mode)
-    ))
-
-(cond (running-xemacs
-       (defconst mime-edit-minor-mime-map nil "Keymap for MIME commands.")
-       (or mime-edit-minor-mime-map
-          (progn
-            (setq mime-edit-minor-mime-map 
-                  (make-sparse-keymap 'mime-edit-minor-mime-map))
-            (define-key
-              mime-edit-minor-mime-map mime-prefix mime-edit-mime-map)
-            ))
-       (add-minor-mode 'mime-edit-mode-flag
-                      '((" MIME-Edit "  mime-transfer-level-string))
-                      mime-edit-minor-mime-map
-                      nil
-                      'mime-edit-toggle-mode)
-       )
-      (t
-       (set-alist 'minor-mode-alist
-                 'mime-edit-mode-flag
-                 '((" MIME-Edit "  mime-transfer-level-string))))
-      )
+(defvar mime-edit-mode-entity-prefix "\C-c\C-x"
+  "Keymap prefix for MIME-Edit mode commands to insert entity or set status.")
+(defvar mime-edit-mode-entity-map (make-sparse-keymap)
+  "Keymap for MIME-Edit mode commands to insert entity or set status.")
+
+(define-key mime-edit-mode-entity-map "\C-t" 'mime-edit-insert-text)
+(define-key mime-edit-mode-entity-map "\C-i" 'mime-edit-insert-file)
+(define-key mime-edit-mode-entity-map "\C-e" 'mime-edit-insert-external)
+(define-key mime-edit-mode-entity-map "\C-v" 'mime-edit-insert-voice)
+(define-key mime-edit-mode-entity-map "\C-y" 'mime-edit-insert-message)
+(define-key mime-edit-mode-entity-map "\C-m" 'mime-edit-insert-mail)
+(define-key mime-edit-mode-entity-map "\C-w" 'mime-edit-insert-signature)
+(define-key mime-edit-mode-entity-map "\C-s" 'mime-edit-insert-signature)
+(define-key mime-edit-mode-entity-map "\C-k" 'mime-edit-insert-key)
+(define-key mime-edit-mode-entity-map "t"    'mime-edit-insert-tag)
+
+(define-key mime-edit-mode-entity-map "7" 'mime-edit-set-transfer-level-7bit)
+(define-key mime-edit-mode-entity-map "8" 'mime-edit-set-transfer-level-8bit)
+(define-key mime-edit-mode-entity-map "/" 'mime-edit-set-split)
+(define-key mime-edit-mode-entity-map "s" 'mime-edit-set-sign)
+(define-key mime-edit-mode-entity-map "v" 'mime-edit-set-sign)
+(define-key mime-edit-mode-entity-map "e" 'mime-edit-set-encrypt)
+(define-key mime-edit-mode-entity-map "h" 'mime-edit-set-encrypt)
+(define-key mime-edit-mode-entity-map "p" 'mime-edit-preview-message)
+(define-key mime-edit-mode-entity-map "\C-z" 'mime-edit-exit)
+(define-key mime-edit-mode-entity-map "?" 'mime-edit-help)
+
+(defvar mime-edit-mode-enclosure-prefix "\C-c\C-m"
+  "Keymap prefix for MIME-Edit mode commands about enclosure.")
+(defvar mime-edit-mode-enclosure-map (make-sparse-keymap)
+  "Keymap for MIME-Edit mode commands about enclosure.")
+
+(define-key mime-edit-mode-enclosure-map
+  "\C-a" 'mime-edit-enclose-alternative-region)
+(define-key mime-edit-mode-enclosure-map
+  "\C-p" 'mime-edit-enclose-parallel-region)
+(define-key mime-edit-mode-enclosure-map
+  "\C-m" 'mime-edit-enclose-mixed-region)
+(define-key mime-edit-mode-enclosure-map
+  "\C-d" 'mime-edit-enclose-digest-region)
+(define-key mime-edit-mode-enclosure-map
+  "\C-s" 'mime-edit-enclose-pgp-signed-region)
+(define-key mime-edit-mode-enclosure-map
+  "\C-e" 'mime-edit-enclose-pgp-encrypted-region)
+(define-key mime-edit-mode-enclosure-map
+  "\C-q" 'mime-edit-enclose-quote-region)
+
+(defvar mime-edit-mode-map (make-sparse-keymap)
+  "Keymap for MIME-Edit mode commands.")
+(define-key mime-edit-mode-map
+  mime-edit-mode-entity-prefix mime-edit-mode-entity-map)
+(define-key mime-edit-mode-map
+  mime-edit-mode-enclosure-prefix mime-edit-mode-enclosure-map)
 
 (defconst mime-edit-menu-title "MIME-Edit")
 
@@ -625,69 +806,70 @@ Tspecials means any character that matches with it in header must be quoted.")
     (parallel  "Enclose as parallel"   mime-edit-enclose-parallel-region)
     (mixed     "Enclose as serial"     mime-edit-enclose-mixed-region)
     (digest    "Enclose as digest"     mime-edit-enclose-digest-region)
-    (signed    "Enclose as signed"     mime-edit-enclose-signed-region)
-    (encrypted "Enclose as encrypted"  mime-edit-enclose-encrypted-region)
+    (signed    "Enclose as signed"     mime-edit-enclose-pgp-signed-region)
+    (encrypted "Enclose as encrypted"  mime-edit-enclose-pgp-encrypted-region)
     (quote     "Verbatim region"       mime-edit-enclose-quote-region)
     (key       "Insert Public Key"     mime-edit-insert-key)
-    (split     "About split"           mime-edit-set-split)
-    (sign      "About sign"            mime-edit-set-sign)
-    (encrypt   "About encryption"      mime-edit-set-encrypt)
+    (split     "Set splitting"         mime-edit-set-split)
+    (sign      "PGP sign"              mime-edit-set-sign)
+    (encrypt   "PGP encrypt"           mime-edit-set-encrypt)
     (preview   "Preview Message"       mime-edit-preview-message)
     (level     "Toggle transfer-level" mime-edit-toggle-transfer-level)
     )
   "MIME-edit menubar entry.")
 
-(defun mime-edit-define-menu-for-emacs19 ()
-  "Define menu for Emacs 19."
-  (define-key (current-local-map) [menu-bar mime-edit]
-    (cons mime-edit-menu-title
-         (make-sparse-keymap mime-edit-menu-title)))
-  (mapcar (function
-          (lambda (item)
-            (define-key (current-local-map)
-              (vector 'menu-bar 'mime-edit (car item))
-              (cons (nth 1 item)(nth 2 item))
+(cond ((featurep 'xemacs)
+       ;; modified by Pekka Marjola <pema@iki.fi>
+       ;;      1995/9/5 (c.f. [tm-en:69])
+       (defun mime-edit-define-menu-for-xemacs ()
+        "Define menu for XEmacs."
+        (cond ((featurep 'menubar)
+               (make-local-variable 'current-menubar)
+               (set-buffer-menubar current-menubar)
+               (add-submenu
+                nil
+                (cons mime-edit-menu-title
+                      (mapcar (function
+                               (lambda (item)
+                                 (vector (nth 1 item)(nth 2 item)
+                                         mime-edit-mode-flag)
+                                 ))
+                              mime-edit-menu-list)))
+               )))
+
+       ;; modified by Steven L. Baur <steve@miranova.com>
+       ;;      1995/12/6 (c.f. [tm-en:209])
+       (or (boundp 'mime-edit-popup-menu-for-xemacs)
+          (setq mime-edit-popup-menu-for-xemacs
+                (append '("MIME Commands" "---")
+                        (mapcar (function (lambda (item)
+                                            (vector (nth 1 item)
+                                                    (nth 2 item)
+                                                    t)))
+                                mime-edit-menu-list)))
+          )
+       )
+      ((>= emacs-major-version 19)
+       (define-key mime-edit-mode-map [menu-bar mime-edit]
+        (cons mime-edit-menu-title
+              (make-sparse-keymap mime-edit-menu-title)))
+       (mapcar (function
+               (lambda (item)
+                 (define-key mime-edit-mode-map
+                   (vector 'menu-bar 'mime-edit (car item))
+                   (cons (nth 1 item)(nth 2 item))
+                   )
+                 ))
+              (reverse mime-edit-menu-list)
               )
-            ))
-         (reverse mime-edit-menu-list)
-         ))
-
-;;; modified by Pekka Marjola <pema@iki.fi>
-;;;    1995/9/5 (c.f. [tm-en:69])
-(defun mime-edit-define-menu-for-xemacs ()
-  "Define menu for Emacs 19."
-  (cond ((featurep 'menubar)
-        (make-local-variable 'current-menubar)
-        (set-buffer-menubar current-menubar)
-        (add-submenu nil
-                     (cons mime-edit-menu-title
-                           (mapcar (function
-                                    (lambda (item)
-                                      (vector (nth 1 item)(nth 2 item)
-                                              mime-edit-mode-flag)
-                                      ))
-                                   mime-edit-menu-list)))
-        )))
-
-;;; modified by Steven L. Baur <steve@miranova.com>
-;;;    1995/12/6 (c.f. [tm-en:209])
-(if (and running-xemacs (not (boundp 'mime-edit-popup-menu-for-xemacs)))
-    (setq mime-edit-popup-menu-for-xemacs
-         (append '("MIME Commands" "---")
-                 (mapcar (function (lambda (item)
-                                     (vector (nth 1 item)
-                                             (nth 2 item)
-                                             t)))
-                         mime-edit-menu-list)))
-  )
-;;; end
-
-(defvar mime-edit-mode-old-local-map nil) ; buffer local variable
+       ))
 
 
 ;;; @ functions
 ;;;
 
+(defvar mime-edit-touched-flag nil)
+
 ;;;###autoload
 (defun mime-edit-mode ()
   "MIME minor mode for editing the tagged MIME message.
@@ -698,40 +880,35 @@ format. The message tag looks like:
        --[[text/plain; charset=ISO-2022-JP][7bit]]
 
 The tag specifies the MIME content type, subtype, optional parameters
-and transfer encoding of the message following the tag. Messages
-without any tag are treated as `text/plain' by default. Charset and
+and transfer encoding of the message following the tag.  Messages
+without any tag are treated as `text/plain' by default.  Charset and
 transfer encoding are automatically defined unless explicitly
-specified. Binary messages such as audio and image are usually hidden.
-The messages in the tagged MIME format are automatically translated
-into a MIME compliant message when exiting this mode.
+specified.  Binary messages such as audio and image are usually
+hidden.  The messages in the tagged MIME format are automatically
+translated into a MIME compliant message when exiting this mode.
 
-Available charsets depend on Emacs version being used. The following
+Available charsets depend on Emacs version being used.  The following
 lists the available charsets of each emacs.
 
-EMACS 18:      US-ASCII is only available.
-NEmacs:                US-ASCII and ISO-2022-JP are available.
-EMACS 19:      US-ASCII and ISO-8859-1 (or other charset) are available.
-XEmacs 19:     US-ASCII and ISO-8859-1 (or other charset) are available.
-Mule:          US-ASCII, ISO-8859-* (except for ISO-8859-5), KOI8-R,
-               ISO-2022-JP, ISO-2022-JP-2, ISO-2022-KR, BIG5 and
-               ISO-2022-INT-1 are available.
+Without mule:  US-ASCII and ISO-8859-1 (or other charset) are available.
+With mule:     US-ASCII, ISO-8859-* (except for ISO-8859-5), KOI8-R,
+               ISO-2022-JP, ISO-2022-JP-2, EUC-KR, CN-GB-2312,
+               CN-BIG5 and ISO-2022-INT-1 are available.
 
 ISO-2022-JP-2 and ISO-2022-INT-1 charsets used in mule is expected to
-be used to represent multilingual text in intermixed manner. Any
+be used to represent multilingual text in intermixed manner.  Any
 languages that has no registered charset are represented as either
 ISO-2022-JP-2 or ISO-2022-INT-1 in mule.
 
-If you want to use non-ISO-8859-1 charset in EMACS 19 or XEmacs 19,
-please set variable `default-mime-charset'. This variable must be
-symbol of which name is a MIME charset.
+If you want to use non-ISO-8859-1 charset in Emacs 19 or XEmacs
+without mule, please set variable `default-mime-charset'.  This
+variable must be symbol of which name is a MIME charset.
 
 If you want to add more charsets in mule, please set variable
-`charsets-mime-charset-alist'. This variable must be alist of which
-key is list of leading-char/charset and value is symbol of MIME
-charset. (leading-char is a term of MULE 1.* and 2.*. charset is a
-term of XEmacs/mule, mule merged EMACS and MULE 3.*) If name of
-coding-system is different as MIME charset, please set variable
-`mime-charset-coding-system-alist'. This variable must be alist of
+`charsets-mime-charset-alist'.  This variable must be alist of which
+key is list of charset and value is symbol of MIME charset.  If name
+of coding-system is different as MIME charset, please set variable
+`mime-charset-coding-system-alist'.  This variable must be alist of
 which key is MIME charset and value is coding-system.
 
 Following commands are available in addition to major mode commands:
@@ -748,24 +925,27 @@ Following commands are available in addition to major mode commands:
 \\[mime-edit-insert-tag]       insert a new MIME tag.
 
 \[make enclosure (maybe multipart)\]
-\\[mime-edit-enclose-alternative-region]       enclose as multipart/alternative.
-\\[mime-edit-enclose-parallel-region]  enclose as multipart/parallel.
-\\[mime-edit-enclose-mixed-region]     enclose as multipart/mixed.
-\\[mime-edit-enclose-digest-region]    enclose as multipart/digest.
-\\[mime-edit-enclose-signed-region]    enclose as PGP signed.
-\\[mime-edit-enclose-encrypted-region] enclose as PGP encrypted.
-\\[mime-edit-enclose-quote-region]     enclose as verbose mode (to avoid to expand tags)
+\\[mime-edit-enclose-alternative-region]   enclose as multipart/alternative.
+\\[mime-edit-enclose-parallel-region]     enclose as multipart/parallel.
+\\[mime-edit-enclose-mixed-region]        enclose as multipart/mixed.
+\\[mime-edit-enclose-digest-region]       enclose as multipart/digest.
+\\[mime-edit-enclose-pgp-signed-region]           enclose as PGP signed.
+\\[mime-edit-enclose-pgp-encrypted-region] enclose as PGP encrypted.
+\\[mime-edit-enclose-quote-region]        enclose as verbose mode
+                                          (to avoid to expand tags)
 
 \[other commands\]
 \\[mime-edit-set-transfer-level-7bit]  set transfer-level as 7.
 \\[mime-edit-set-transfer-level-8bit]  set transfer-level as 8.
-\\[mime-edit-set-split]        set message splitting mode.
-\\[mime-edit-set-sign] set PGP-sign mode.
-\\[mime-edit-set-encrypt]      set PGP-encryption mode.
-\\[mime-edit-preview-message]  preview editing MIME message.
-\\[mime-edit-exit]     exit and translate into a MIME compliant message.
-\\[mime-edit-help]     show this help.
-\\[mime-edit-maybe-translate]  exit and translate if in MIME mode, then split.
+\\[mime-edit-set-split]                        set message splitting mode.
+\\[mime-edit-set-sign]                 set PGP-sign mode.
+\\[mime-edit-set-encrypt]              set PGP-encryption mode.
+\\[mime-edit-preview-message]          preview editing MIME message.
+\\[mime-edit-exit]                     exit and translate into a MIME
+                                       compliant message.
+\\[mime-edit-help]                     show this help.
+\\[mime-edit-maybe-translate]          exit and translate if in MIME mode,
+                                       then split.
 
 Additional commands are available in some major modes:
 C-c C-c                exit, translate and run the original command.
@@ -790,7 +970,7 @@ TABs at the beginning of the line are not a part of the message:
        --[[audio/basic][base64]]...audio encoded in base64 here...
 
 User customizable variables (not documented all of them):
- mime-prefix
+ mime-edit-prefix
     Specifies a key prefix for MIME minor mode commands.
 
  mime-ignore-preceding-spaces
@@ -827,37 +1007,53 @@ User customizable variables (not documented all of them):
     non-nil."
   (interactive)
   (if mime-edit-mode-flag
+      (mime-edit-exit)
+    (if mime-edit-touched-flag
+       (mime-edit-again)
+      (make-local-variable 'mime-edit-touched-flag)
+      (setq mime-edit-touched-flag t)
+      (turn-on-mime-edit)
+      )))
+
+
+(cond ((featurep 'xemacs)
+       (add-minor-mode 'mime-edit-mode-flag
+                      '((" MIME-Edit "  mime-transfer-level-string))
+                      mime-edit-mode-map
+                      nil
+                      'mime-edit-mode)
+       )
+      (t
+       (set-alist 'minor-mode-alist
+                 'mime-edit-mode-flag
+                 '((" MIME-Edit "  mime-transfer-level-string)))
+       (set-alist 'minor-mode-map-alist
+                 'mime-edit-mode-flag
+                 mime-edit-mode-map)
+       ))
+
+
+;;;###autoload
+(defun turn-on-mime-edit ()
+  "Unconditionally turn on MIME-Edit mode."
+  (interactive)
+  (if mime-edit-mode-flag
       (error "You are already editing a MIME message.")
     (setq mime-edit-mode-flag t)
-    ;; Remember old key bindings.
-    (if running-xemacs
-       (use-local-map (or (current-local-map) (make-sparse-keymap)))
-      (make-local-variable 'mime-edit-mode-old-local-map)
-      (setq mime-edit-mode-old-local-map (current-local-map))
-      ;; Add MIME commands to current local map.
-      (use-local-map (copy-keymap (or (current-local-map)
-                                     (make-sparse-keymap))))
-      )
-    (if (not (lookup-key (current-local-map) mime-prefix))
-       (define-key (current-local-map) mime-prefix mime-edit-mime-map))
 
     ;; Set transfer level into mode line
     ;;
     (setq mime-transfer-level-string
          (mime-encoding-name mime-transfer-level 'not-omit))
     (force-mode-line-update)
-    
-    ;; Define menu.  Menus for other emacs implementations are
-    ;; welcome.
-    (cond (running-xemacs
-          (mime-edit-define-menu-for-xemacs))
-         ((>= emacs-major-version 19)
-          (mime-edit-define-menu-for-emacs19)
-          ))
-    ;; end
-    
+
+    ;; Define menu for XEmacs.
+    (if (featurep 'xemacs)
+       (mime-edit-define-menu-for-xemacs)
+      )
+
     (enable-invisible)
-    
+
     ;; I don't care about saving these.
     (setq paragraph-start
          (regexp-or mime-edit-single-part-tag-regexp
@@ -867,13 +1063,14 @@ User customizable variables (not documented all of them):
                     paragraph-separate))
     (run-hooks 'mime-edit-mode-hook)
     (message
+     "%s"
      (substitute-command-keys
       "Type \\[mime-edit-exit] to exit MIME mode, and type \\[mime-edit-help] to get help."))
     ))
 
 ;;;###autoload
-(defalias 'edit-mime 'mime-edit-mode)          ; for convenience
-(defalias 'mime-mode 'mime-edit-mode)          ; for convenience
+(defalias 'edit-mime 'turn-on-mime-edit) ; for convenience
+
 
 (defun mime-edit-exit (&optional nomime no-error)
   "Translate the tagged MIME message into a MIME compliant message.
@@ -890,12 +1087,10 @@ just return to previous mode."
          (mime-edit-translate-buffer)))
     ;; Restore previous state.
     (setq mime-edit-mode-flag nil)
-    (cond (running-xemacs
-          (if (featurep 'menubar) 
-              (delete-menu-item (list mime-edit-menu-title))))
-         (t
-          (use-local-map mime-edit-mode-old-local-map)))
-    
+    (if (and (featurep 'xemacs)
+            (featurep 'menubar))
+       (delete-menu-item (list mime-edit-menu-title))
+      )
     (end-of-invisible)
     (set-buffer-modified-p (buffer-modified-p))
     (run-hooks 'mime-edit-exit-hook)
@@ -916,26 +1111,26 @@ just return to previous mode."
     (princ (documentation 'mime-edit-mode))
     (print-help-return-message)))
 
-(defun mime-edit-insert-text ()
+(defun mime-edit-insert-text (&optional subtype)
   "Insert a text message.
-Charset is automatically obtained from the `charsets-mime-charset-alist'."
+Charset is automatically obtained from the `charsets-mime-charset-alist'.
+If optional argument SUBTYPE is not nil, text/SUBTYPE tag is inserted."
   (interactive)
-  (let ((ret (mime-edit-insert-tag "text" nil nil)))
-  (if ret
-      (progn
-       (if (looking-at mime-edit-single-part-tag-regexp)
-           (progn
-             ;; Make a space between the following message.
-             (insert "\n")
-             (forward-char -1)
-             ))
-       (if (and (member (second ret) '("enriched" "richtext"))
-                (fboundp 'enriched-mode)
-                )
-           (enriched-mode t)
-         (if (boundp 'enriched-mode)
-             (enriched-mode nil)
-           ))))))
+  (let ((ret (mime-edit-insert-tag "text" subtype nil)))
+    (when ret
+      (if (looking-at mime-edit-single-part-tag-regexp)
+         (progn
+           ;; Make a space between the following message.
+           (insert "\n")
+           (forward-char -1)
+           ))
+      (if (and (member (cadr ret) '("enriched"))
+              (fboundp 'enriched-mode))
+         (enriched-mode t)
+       (if (boundp 'enriched-mode)
+           (enriched-mode -1)
+         ))
+      )))
 
 (defun mime-edit-insert-file (file &optional verbose)
   "Insert a message from a file."
@@ -1017,7 +1212,7 @@ Charset is automatically obtained from the `charsets-mime-charset-alist'."
   (let ((encoding
         (completing-read
          "What transfer encoding: "
-         mime-file-encoding-method-alist nil t nil)))
+         (mime-encoding-alist) nil t nil)))
     (mime-edit-insert-tag "audio" "basic" nil)
     (mime-edit-define-encoding encoding)
     (save-restriction
@@ -1036,8 +1231,9 @@ Charset is automatically obtained from the `charsets-mime-charset-alist'."
   (let ((signature-insert-hook
          (function
           (lambda ()
-            (apply (function mime-edit-insert-tag)
-                   (mime-find-file-type signature-file-name))
+           (let ((items (mime-find-file-type signature-file-name)))
+             (apply (function mime-edit-insert-tag)
+                    (car items) (cadr items) (list (caddr items))))
             )))
         )
     (insert-signature arg)
@@ -1144,7 +1340,7 @@ Optional argument ENCODING specifies an encoding method such as base64."
 
 (defun mime-edit-goto-tag ()
   "Search for the beginning of the tagged MIME message."
-  (let ((current (point)) multipart)
+  (let ((current (point)))
     (if (looking-at mime-edit-tag-regexp)
        t
       ;; At first, go to the end.
@@ -1154,7 +1350,7 @@ Optional argument ENCODING specifies an encoding method such as base64."
            (t
             (goto-char (point-max))
             ))
-      ;; Then search for the beginning. 
+      ;; Then search for the beginning.
       (re-search-backward mime-edit-end-tag-regexp nil t)
       (or (looking-at mime-edit-beginning-tag-regexp)
          ;; Restore previous point.
@@ -1189,26 +1385,25 @@ Optional argument ENCODING specifies an encoding method such as base64."
 (defun mime-edit-content-end ()
   "Return the point of the end of content."
   (save-excursion
-    (let ((beg (point)))
-      (if (mime-edit-goto-tag)
-         (let ((top (point)))
-           (goto-char (match-end 0))
-           (if (invisible-p (point))
-               (next-visible-point (point))
-             ;; Move to the end of this text.
-             (if (re-search-forward mime-edit-tag-regexp nil 'move)
-                 ;; Don't forget a multiline tag.
-                 (goto-char (match-beginning 0))
-               )
-             (point)
-             ))
-       ;; Assume the message begins with text/plain.
-       (goto-char (mime-edit-content-beginning))
-       (if (re-search-forward mime-edit-tag-regexp nil 'move)
-           ;; Don't forget a multiline tag.
-           (goto-char (match-beginning 0)))
-       (point))
-      )))
+    (if (mime-edit-goto-tag)
+       (progn
+         (goto-char (match-end 0))
+         (if (invisible-p (point))
+             (next-visible-point (point))
+           ;; Move to the end of this text.
+           (if (re-search-forward mime-edit-tag-regexp nil 'move)
+               ;; Don't forget a multiline tag.
+               (goto-char (match-beginning 0))
+             )
+           (point)
+           ))
+      ;; Assume the message begins with text/plain.
+      (goto-char (mime-edit-content-beginning))
+      (if (re-search-forward mime-edit-tag-regexp nil 'move)
+         ;; Don't forget a multiline tag.
+         (goto-char (match-beginning 0)))
+      (point))
+    ))
 
 (defun mime-edit-define-charset (charset)
   "Set charset of current tag to CHARSET."
@@ -1220,7 +1415,11 @@ Optional argument ENCODING specifies an encoding method such as base64."
           (mime-create-tag
            (mime-edit-set-parameter
             (mime-edit-get-contype tag)
-            "charset" (upcase (symbol-name charset)))
+            "charset"
+            (let ((comment (get charset 'mime-charset-comment)))
+              (if comment
+                  (concat (upcase (symbol-name charset)) " (" comment ")")
+                (upcase (symbol-name charset)))))
            (mime-edit-get-encoding tag)))
          ))))
 
@@ -1310,7 +1509,7 @@ Nil if no such parameter."
        ;; Change value
        (concat (substring ctype 0 (match-beginning 1))
                parameter "=" value
-               (substring contype (match-end 1))
+               (substring ctype (match-end 1))
                opt-fields)
       (concat ctype "; " parameter "=" value opt-fields)
       )))
@@ -1408,7 +1607,7 @@ Optional DELIMITER specifies parameter delimiter (';' by default)."
 
 (defun mime-prompt-for-parameter (parameter)
   "Ask for PARAMETER.
-Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
+Parameter must be '(PROMPT CHOICE1 (CHOICE2...))."
   (let* ((prompt (car parameter))
         (choices (mapcar (function
                           (lambda (e)
@@ -1440,13 +1639,13 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
     ))
 
 (defun mime-prompt-for-encoding (default)
-  "Ask for Content-Transfer-Encoding. [mime-edit.el]"
+  "Ask for Content-Transfer-Encoding."
   (let (encoding)
     (while (string=
            (setq encoding
                  (completing-read
                   "What transfer encoding: "
-                  mime-file-encoding-method-alist nil t default)
+                  (mime-encoding-alist) nil t default)
                  )
            ""))
     encoding))
@@ -1462,13 +1661,13 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
 
 (defun mime-edit-translate-header ()
   "Encode the message header into network representation."
-  (eword-encode-header 'code-conversion)
-  (run-hooks 'mime-edit-translate-header-hook)
-  )
+  (mime-encode-header-in-buffer 'code-conversion)
+  (run-hooks 'mime-edit-translate-header-hook))
 
 (defun mime-edit-translate-buffer ()
   "Encode the tagged MIME message in current buffer in MIME compliant message."
   (interactive)
+  (undo-boundary)
   (if (catch 'mime-edit-error
        (save-excursion
          (run-hooks 'mime-edit-translate-buffer-hook)
@@ -1484,21 +1683,17 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
       (let ((bb (match-beginning 0))
            (be (match-end 0))
            (type (buffer-substring (match-beginning 1)(match-end 1)))
-           end-exp eb ee)
+           end-exp eb)
        (setq end-exp (format "--}-<<%s>>\n" type))
        (widen)
        (if (re-search-forward end-exp nil t)
-           (progn
-             (setq eb (match-beginning 0))
-             (setq ee (match-end 0))
-             )
+           (setq eb (match-beginning 0))
          (setq eb (point-max))
-         (setq ee (point-max))
          )
        (narrow-to-region be eb)
        (goto-char be)
        (if (re-search-forward mime-edit-multipart-beginning-regexp nil t)
-           (let (ret)
+           (progn
              (narrow-to-region (match-beginning 0)(point-max))
              (mime-edit-find-inmost)
              )
@@ -1531,21 +1726,24 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
          (cond ((string-equal type "quote")
                 (mime-edit-enquote-region bb eb)
                 )
-               ((string-equal type "signed")
-                (cond ((eq mime-edit-signing-type 'pgp-elkins)
-                       (mime-edit-sign-pgp-elkins bb eb boundary)
-                       )
-                      ((eq mime-edit-signing-type 'pgp-kazu)
-                       (mime-edit-sign-pgp-kazu bb eb boundary)
-                       ))
+               ((string-equal type "pgp-signed")
+                (mime-edit-sign-pgp-mime bb eb boundary)
+                )
+               ((string-equal type "pgp-encrypted")
+                (mime-edit-encrypt-pgp-mime bb eb boundary)
+                )
+               ((string-equal type "kazu-signed")
+                (mime-edit-sign-pgp-kazu bb eb boundary)
+                )
+               ((string-equal type "kazu-encrypted")
+                (mime-edit-encrypt-pgp-kazu bb eb boundary)
+                )
+               ((string-equal type "smime-signed")
+                (mime-edit-sign-smime bb eb boundary)
+                )
+               ((string-equal type "smime-encrypted")
+                (mime-edit-encrypt-smime bb eb boundary)
                 )
-               ((string-equal type "encrypted")
-                (cond ((eq mime-edit-encrypting-type 'pgp-elkins)
-                       (mime-edit-encrypt-pgp-elkins bb eb boundary)
-                       )
-                      ((eq mime-edit-encrypting-type 'pgp-kazu)
-                       (mime-edit-encrypt-pgp-kazu bb eb boundary)
-                       )))
                (t
                 (setq boundary
                       (nth 2 (mime-edit-translate-region bb eb
@@ -1579,27 +1777,57 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
          (replace-match (concat "-" (substring tag 2)))
          )))))
 
-(defun mime-edit-sign-pgp-elkins (beg end boundary)
+(defvar mime-edit-pgp-user-id nil)
+
+(defun mime-edit-sign-pgp-mime (beg end boundary)
   (save-excursion
     (save-restriction
-      (narrow-to-region beg end)
-      (let* ((ret
-             (mime-edit-translate-region beg end boundary))
+      (let* ((from (std11-field-body "From" mail-header-separator))
+            (ret (progn 
+                   (narrow-to-region beg end)
+                   (mime-edit-translate-region beg end boundary)))
             (ctype    (car ret))
             (encoding (nth 1 ret))
-            (parts    (nth 3 ret))
             (pgp-boundary (concat "pgp-sign-" boundary))
-            )
+            micalg)
        (goto-char beg)
        (insert (format "Content-Type: %s\n" ctype))
        (if encoding
            (insert (format "Content-Transfer-Encoding: %s\n" encoding))
          )
        (insert "\n")
-       (or (funcall (pgp-function 'mime-sign)
-                    (point-min)(point-max) nil nil pgp-boundary)
+       (or (let ((pgg-default-user-id 
+                  (or mime-edit-pgp-user-id
+                      (if from 
+                          (nth 1 (std11-extract-address-components from))
+                        pgg-default-user-id))))
+             (pgg-sign-region (point-min)(point-max)))
            (throw 'mime-edit-error 'pgp-error)
            )
+       (setq micalg
+             (cdr (assq 'hash-algorithm
+                        (cdar (with-current-buffer pgg-output-buffer
+                                (pgg-parse-armor-region 
+                                 (point-min)(point-max))))))
+             micalg 
+             (if micalg
+                 (concat "; micalg=pgp-" (downcase (symbol-name micalg)))
+               ""))
+       (goto-char beg)
+       (insert (format "--[[multipart/signed;
+ boundary=\"%s\"%s;
+ protocol=\"application/pgp-signature\"][7bit]]
+--%s
+" pgp-boundary micalg pgp-boundary))
+       (goto-char (point-max))
+       (insert (format "\n--%s
+Content-Type: application/pgp-signature
+Content-Transfer-Encoding: 7bit
+
+" pgp-boundary))
+       (insert-buffer-substring pgg-output-buffer)
+       (goto-char (point-max))
+       (insert (format "\n--%s--\n" pgp-boundary))
        ))))
 
 (defvar mime-edit-encrypt-recipient-fields-list '("To" "cc"))
@@ -1636,34 +1864,45 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
     (vector from recipients header)
     ))
 
-(defun mime-edit-encrypt-pgp-elkins (beg end boundary)
+(defun mime-edit-encrypt-pgp-mime (beg end boundary)
   (save-excursion
     (save-restriction
       (let (from recipients header)
-       (let ((ret (mime-edit-make-encrypt-recipient-header)))
-         (setq from (aref ret 0)
-               recipients (aref ret 1)
-               header (aref ret 2))
+        (let ((ret (mime-edit-make-encrypt-recipient-header)))
+          (setq from (aref ret 0)
+                recipients (aref ret 1)
+                header (aref ret 2))
          )
-       (narrow-to-region beg end)
-       (let* ((ret
-               (mime-edit-translate-region beg end boundary))
-              (ctype    (car ret))
-              (encoding (nth 1 ret))
-              (parts    (nth 3 ret))
-              (pgp-boundary (concat "pgp-" boundary))
-              )
-         (goto-char beg)
-         (insert header)
-         (insert (format "Content-Type: %s\n" ctype))
-         (if encoding
-             (insert (format "Content-Transfer-Encoding: %s\n" encoding))
-           )
-         (insert "\n")
-         (or (funcall (pgp-function 'encrypt)
-                      recipients (point-min) (point-max) from)
+        (narrow-to-region beg end)
+        (let* ((ret
+                (mime-edit-translate-region beg end boundary))
+               (ctype    (car ret))
+               (encoding (nth 1 ret))
+               (pgp-boundary (concat "pgp-" boundary)))
+          (goto-char beg)
+          (insert header)
+          (insert (format "Content-Type: %s\n" ctype))
+          (if encoding
+              (insert (format "Content-Transfer-Encoding: %s\n" encoding))
+            )
+          (insert "\n")
+         (mime-encode-header-in-buffer)
+         (or (let ((pgg-default-user-id 
+                    (or mime-edit-pgp-user-id
+                        (if from 
+                            (nth 1 (std11-extract-address-components from))
+                          pgg-default-user-id))))                   
+               (pgg-encrypt-region 
+                (point-min) (point-max) 
+                (mapcar (lambda (recipient)
+                          (nth 1 (std11-extract-address-components
+                                  recipient)))
+                        (split-string recipients 
+                                      "\\([ \t\n]*,[ \t\n]*\\)+")))
+               )
              (throw 'mime-edit-error 'pgp-error)
              )
+         (delete-region (point-min)(point-max))
          (goto-char beg)
          (insert (format "--[[multipart/encrypted;
  boundary=\"%s\";
@@ -1676,6 +1915,7 @@ Content-Type: application/octet-stream
 Content-Transfer-Encoding: 7bit
 
 " pgp-boundary pgp-boundary pgp-boundary))
+         (insert-buffer-substring pgg-output-buffer)
          (goto-char (point-max))
          (insert (format "\n--%s--\n" pgp-boundary))
          )))))
@@ -1687,18 +1927,14 @@ Content-Transfer-Encoding: 7bit
       (let* ((ret
              (mime-edit-translate-region beg end boundary))
             (ctype    (car ret))
-            (encoding (nth 1 ret))
-            (parts    (nth 3 ret))
-            )
+            (encoding (nth 1 ret)))
        (goto-char beg)
        (insert (format "Content-Type: %s\n" ctype))
        (if encoding
            (insert (format "Content-Transfer-Encoding: %s\n" encoding))
          )
        (insert "\n")
-       (or (as-binary-process
-            (funcall (pgp-function 'traditional-sign)
-                     beg (point-max)))
+       (or (pgg-sign-region beg (point-max) 'clearsign)
            (throw 'mime-edit-error 'pgp-error)
            )
        (goto-char beg)
@@ -1709,10 +1945,9 @@ Content-Transfer-Encoding: 7bit
 
 (defun mime-edit-encrypt-pgp-kazu (beg end boundary)
   (save-excursion
-    (let (from recipients header)
+    (let (recipients header)
       (let ((ret (mime-edit-make-encrypt-recipient-header)))
-       (setq from (aref ret 0)
-             recipients (aref ret 1)
+       (setq recipients (aref ret 1)
              header (aref ret 2))
        )
       (save-restriction
@@ -1720,9 +1955,7 @@ Content-Transfer-Encoding: 7bit
        (let* ((ret
                (mime-edit-translate-region beg end boundary))
               (ctype    (car ret))
-              (encoding (nth 1 ret))
-              (parts    (nth 3 ret))
-              )
+              (encoding (nth 1 ret)))
          (goto-char beg)
          (insert header)
          (insert (format "Content-Type: %s\n" ctype))
@@ -1730,10 +1963,7 @@ Content-Transfer-Encoding: 7bit
              (insert (format "Content-Transfer-Encoding: %s\n" encoding))
            )
          (insert "\n")
-         (or (as-binary-process
-              (funcall (pgp-function 'encrypt)
-                       recipients beg (point-max) nil 'maybe)
-              )
+         (or (pgg-encrypt-region beg (point-max) recipients)
              (throw 'mime-edit-error 'pgp-error)
              )
          (goto-char beg)
@@ -1742,6 +1972,78 @@ Content-Transfer-Encoding: 7bit
          ))
       )))
 
+(defun mime-edit-sign-smime (beg end boundary)
+  (save-excursion
+    (save-restriction
+      (let* ((ret (progn 
+                   (narrow-to-region beg end)
+                   (mime-edit-translate-region beg end boundary)))
+            (ctype    (car ret))
+            (encoding (nth 1 ret))
+            (smime-boundary (concat "smime-sign-" boundary)))
+       (goto-char beg)
+       (insert (format "Content-Type: %s\n" ctype))
+       (if encoding
+           (insert (format "Content-Transfer-Encoding: %s\n" encoding))
+         )
+       (insert "\n")
+       (let (buffer-undo-list)
+         (goto-char (point-min))
+         (while (progn (end-of-line) (not (eobp)))
+           (insert "\r")
+           (forward-line 1))
+         (or (prog1 (smime-sign-region (point-min)(point-max))
+               (push nil buffer-undo-list)
+               (ignore-errors (undo)))
+             (throw 'mime-edit-error 'pgp-error)
+             ))
+       (goto-char beg)
+       (insert (format "--[[multipart/signed;
+ boundary=\"%s\"; micalg=sha1;
+ protocol=\"application/pkcs7-signature\"][7bit]]
+--%s
+" smime-boundary smime-boundary))
+       (goto-char (point-max))
+       (insert (format "\n--%s
+Content-Type: application/pkcs7-signature; name=\"smime.p7s\"
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment; filename=\"smime.p7s\"
+Content-Description: S/MIME Cryptographic Signature
+
+"  smime-boundary))
+       (insert-buffer-substring smime-output-buffer)
+       (goto-char (point-max))
+       (insert (format "\n--%s--\n" smime-boundary))
+       ))))
+
+(defun mime-edit-encrypt-smime (beg end boundary)
+  (save-excursion
+    (save-restriction
+      (let* ((ret (progn 
+                   (narrow-to-region beg end)
+                   (mime-edit-translate-region beg end boundary)))
+            (ctype    (car ret))
+            (encoding (nth 1 ret)))
+       (goto-char beg)
+       (insert (format "Content-Type: %s\n" ctype))
+       (if encoding
+           (insert (format "Content-Transfer-Encoding: %s\n" encoding))
+         )
+       (insert "\n")
+       (goto-char (point-min))
+       (while (progn (end-of-line) (not (eobp)))
+         (insert "\r")
+         (forward-line 1))
+       (or (smime-encrypt-region (point-min)(point-max))
+           (throw 'mime-edit-error 'pgp-error)
+           )
+       (delete-region (point-min)(point-max))
+       (insert "--[[application/pkcs7-mime; name=\"smime.p7m\"
+Content-Disposition: attachment; filename=\"smime.p7m\"
+Content-Description: S/MIME Encrypted Message][base64]]\n")
+       (insert-buffer-substring smime-output-buffer)
+       ))))
+
 (defsubst replace-space-with-underline (str)
   (mapconcat (function
              (lambda (arg)
@@ -1792,13 +2094,13 @@ Content-Transfer-Encoding: 7bit
       (let ((contype (car ret))                ;Content-Type
            (encoding (nth 1 ret))      ;Content-Transfer-Encoding
            )
-       ;; Insert X-Emacs field
-       (and mime-edit-insert-x-emacs-field
-            (or (mail-position-on-field "X-Emacs")
-                (insert mime-edit-x-emacs-value)
+       ;; Insert User-Agent field
+       (and mime-edit-insert-user-agent-field
+            (or (mail-position-on-field "User-Agent")
+                (insert mime-edit-user-agent-value)
                 ))
        ;; Make primary MIME headers.
-       (or (mail-position-on-field "Mime-Version")
+       (or (mail-position-on-field "MIME-Version")
            (insert mime-edit-mime-version-value))
        ;; Remove old Content-Type and other fields.
        (save-restriction
@@ -1817,24 +2119,27 @@ Content-Transfer-Encoding: 7bit
              (insert encoding)))
        ))))
 
-(defun mime-edit-translate-single-part-tag (&optional prefix)
+(defun mime-edit-translate-single-part-tag (boundary &optional prefix)
+  "Translate single-part-tag to MIME header."
   (if (re-search-forward mime-edit-single-part-tag-regexp nil t)
       (let* ((beg (match-beginning 0))
             (end (match-end 0))
-            (tag (buffer-substring beg end))
-            )
+            (tag (buffer-substring beg end)))
        (delete-region beg end)
-       (setq contype (mime-edit-get-contype tag))
-       (setq encoding (mime-edit-get-encoding tag))
-       (insert (concat prefix "--" boundary "\n"))
-       (save-restriction
-         (narrow-to-region (point)(point))
-         (insert "Content-Type: " contype "\n")
-         (if encoding
-             (insert "Content-Transfer-Encoding: " encoding "\n"))
-         (eword-encode-header)
-         )
-       t)))
+       (let ((contype (mime-edit-get-contype tag))
+             (encoding (mime-edit-get-encoding tag)))
+         (insert (concat prefix "--" boundary "\n"))
+         (save-restriction
+           (narrow-to-region (point)(point))
+           (insert "Content-Type: " contype "\n")
+           (if encoding
+               (insert "Content-Transfer-Encoding: " encoding "\n"))
+           (mime-encode-header-in-buffer))
+         (cons (and contype
+                    (downcase contype))
+               (and encoding
+                    (downcase encoding))))
+       )))
 
 (defun mime-edit-translate-region (beg end &optional boundary multipart)
   (or boundary
@@ -1870,23 +2175,26 @@ Content-Transfer-Encoding: 7bit
         (t
          ;; It's a multipart message.
          (goto-char (point-min))
-         (and (mime-edit-translate-single-part-tag)
-              (while (mime-edit-translate-single-part-tag "\n"))
-              )
-         ;; Define Content-Type as "multipart/mixed".
-         (setq contype
-               (concat "multipart/mixed;\n boundary=\"" boundary "\""))
-         ;; Content-Transfer-Encoding must be "7bit".
-         ;; The following encoding can be `nil', but is
-         ;; specified as is since there is no way that a user
-         ;; specifies it.
-         (setq encoding "7bit")
-         ;; Insert the trailer.
-         (goto-char (point-max))
-         (insert "\n--" boundary "--\n")
-         ))
-       (list contype encoding boundary nparts)
-       ))))
+         (let ((prio mime-content-transfer-encoding-priority-list)
+               part-info nprio)
+           (when (setq part-info
+                       (mime-edit-translate-single-part-tag boundary))
+             (and (setq nprio (member (cdr part-info) prio))
+                  (setq prio nprio))
+             (while (setq part-info
+                          (mime-edit-translate-single-part-tag boundary "\n"))
+               (and (setq nprio (member (cdr part-info) prio))
+                    (setq prio nprio))))
+           ;; Define Content-Type as "multipart/mixed".
+           (setq contype
+                 (concat "multipart/mixed;\n boundary=\"" boundary "\""))
+           (setq encoding (car prio))
+           ;; Insert the trailer.
+           (goto-char (point-max))
+           (insert "\n--" boundary "--\n")
+           )))
+        (list contype encoding boundary nparts)
+        ))))
 
 (defun mime-edit-normalize-body ()
   "Normalize the body part by inserting appropriate message tags."
@@ -1928,12 +2236,10 @@ Content-Transfer-Encoding: 7bit
                          (intern (downcase charset))
                        (mime-edit-choose-charset)))
        (mime-edit-define-charset charset)
-       (cond ((string-equal contype "text/x-rot13-47")
+       (cond ((string-equal contype "text/x-rot13-47-48")
               (save-excursion
                 (forward-line)
-                (set-mark (point))
-                (goto-char (mime-edit-content-end))
-                (tm:caesar-region)
+                (mule-caesar-region (point) (mime-edit-content-end))
                 ))
              ((string-equal contype "text/enriched")
               (save-excursion
@@ -1950,7 +2256,7 @@ Content-Transfer-Encoding: 7bit
                    ;;                        (point)
                    ;;                        'hard t)))
                   ;; End patch for hard newlines
-                  (enriched-encode beg end)
+                  (enriched-encode beg end nil)
                   (goto-char beg)
                   (if (search-forward "\n\n")
                       (delete-region beg (match-end 0))
@@ -1960,15 +2266,51 @@ Content-Transfer-Encoding: 7bit
        ;; Define encoding and encode text if necessary.
        (or encoding    ;Encoding is not specified.
            (let* ((encoding
-                   (cdr
-                    (assq charset
-                          mime-edit-charset-default-encoding-alist)
-                    ))
-                  (beg (mime-edit-content-beginning))
-                  )
+                   (let (bits conv)
+                     (let ((ret (cdr (assq charset mime-charset-type-list))))
+                       (if ret
+                           (setq bits (car ret)
+                                 conv (nth 1 ret))
+                         (setq bits 8
+                               conv "quoted-printable")))
+                     (if (<= bits mime-transfer-level)
+                         (mime-encoding-name bits)
+                       conv)))
+                  (beg (mime-edit-content-beginning)))
              (encode-mime-charset-region beg (mime-edit-content-end)
                                          charset)
-             (mime-encode-region beg (mime-edit-content-end) encoding)
+             ;; Protect "From " in beginning of line
+             (save-restriction
+               (narrow-to-region beg (mime-edit-content-end))
+               (goto-char beg)
+               (let (case-fold-search)
+                 (if (re-search-forward "^From " nil t)
+                     (unless encoding
+                       (if (memq charset '(iso-2022-jp
+                                           iso-2022-jp-2
+                                           iso-2022-int-1
+                                           x-ctext))
+                           (while (progn
+                                    (replace-match "\e(BFrom ")
+                                    (re-search-forward "^From " nil t)
+                                    ))
+                         (setq encoding "quoted-printable")
+                         )))))
+             ;; canonicalize line break code
+             (or (member encoding '(nil "7bit" "8bit" "quoted-printable"))
+                 (save-restriction
+                   (narrow-to-region beg (mime-edit-content-end))
+                   (goto-char beg)
+                   (while (re-search-forward "\\(\\=\\|[^\r]\\)\n" nil t)
+                     ;; Don't use this in the multibyte buffer since it may
+                     ;; convert the unibyte string into multibyte.
+                     ;;;;(replace-match "\\1\r\n"))))
+                     (backward-char 1)
+                     (insert "\r")
+                     (forward-char 1))))
+             (goto-char beg)
+             (mime-encode-region beg (mime-edit-content-end)
+                                 (or encoding "7bit"))
              (mime-edit-define-encoding encoding)
              ))
        (goto-char (mime-edit-content-end))
@@ -1979,9 +2321,7 @@ Content-Transfer-Encoding: 7bit
        ;; encoded.
        (let* ((encoding "base64")      ;Encode in BASE64 by default.
               (beg (mime-edit-content-beginning))
-              (end (mime-edit-content-end))
-              (body (buffer-substring beg end))
-              )
+              (end (mime-edit-content-end)))
          (mime-encode-region beg end encoding)
          (mime-edit-define-encoding encoding))
        (forward-line 1)
@@ -1994,8 +2334,7 @@ Content-Transfer-Encoding: 7bit
     (goto-char (point-min))
     (while (re-search-forward regexp nil t)
       (delete-region (match-beginning 0)
-                    (progn (forward-line 1) (point)))
-      )))
+                    (1+ (std11-field-end))))))
 
 \f
 ;;;
@@ -2006,7 +2345,7 @@ Content-Transfer-Encoding: 7bit
 
 (defun mime-edit-voice-recorder-for-sun (encoding)
   "Record voice in a buffer using Sun audio device,
-and insert data encoded as ENCODING. [mime-edit.el]"
+and insert data encoded as ENCODING."
   (message "Start the recording on %s.  Type C-g to finish the recording..."
           (system-name))
   (mime-insert-encoded-file "/dev/audio" encoding)
@@ -2065,69 +2404,86 @@ and insert data encoded as ENCODING. [mime-edit.el]"
 ;;; @ multipart enclosure
 ;;;
 
-(defun mime-edit-enclose-region (type beg end)
+(defun mime-edit-enclose-region-internal (type beg end)
   (save-excursion
     (goto-char beg)
-    (let ((current (point)))
-      (save-restriction
-       (narrow-to-region beg end)
-       (insert (format "--<<%s>>-{\n" type))
-       (goto-char (point-max))
-       (insert (format "--}-<<%s>>\n" type))
-       (goto-char (point-max))
+    (save-restriction
+      (narrow-to-region beg end)
+      (insert (format "--<<%s>>-{\n" type))
+      (goto-char (point-max))
+      (insert (format "--}-<<%s>>\n" type))
+      (goto-char (point-max))
+      )
+    (or (looking-at mime-edit-beginning-tag-regexp)
+       (eobp)
+       (insert (mime-make-text-tag) "\n")
        )
-      (or (looking-at mime-edit-beginning-tag-regexp)
-         (eobp)
-         (insert (mime-make-text-tag) "\n")
-         )
-      )))
+    ))
 
 (defun mime-edit-enclose-quote-region (beg end)
   (interactive "*r")
-  (mime-edit-enclose-region "quote" beg end)
+  (mime-edit-enclose-region-internal 'quote beg end)
   )
 
 (defun mime-edit-enclose-mixed-region (beg end)
   (interactive "*r")
-  (mime-edit-enclose-region "mixed" beg end)
+  (mime-edit-enclose-region-internal 'mixed beg end)
   )
 
 (defun mime-edit-enclose-parallel-region (beg end)
   (interactive "*r")
-  (mime-edit-enclose-region "parallel" beg end)
+  (mime-edit-enclose-region-internal 'parallel beg end)
   )
 
 (defun mime-edit-enclose-digest-region (beg end)
   (interactive "*r")
-  (mime-edit-enclose-region "digest" beg end)
+  (mime-edit-enclose-region-internal 'digest beg end)
   )
 
 (defun mime-edit-enclose-alternative-region (beg end)
   (interactive "*r")
-  (mime-edit-enclose-region "alternative" beg end)
+  (mime-edit-enclose-region-internal 'alternative beg end)
   )
 
-(defun mime-edit-enclose-signed-region (beg end)
+(defun mime-edit-enclose-pgp-signed-region (beg end)
   (interactive "*r")
-  (if mime-edit-signing-type
-      (mime-edit-enclose-region "signed" beg end)
-    (message "Please specify signing type.")
-    ))
+  (mime-edit-enclose-region-internal 'pgp-signed beg end)
+  )
 
-(defun mime-edit-enclose-encrypted-region (beg end)
+(defun mime-edit-enclose-pgp-encrypted-region (beg end)
   (interactive "*r")
-  (if mime-edit-signing-type
-      (mime-edit-enclose-region "encrypted" beg end)
-    (message "Please specify encrypting type.")
-    ))
+  (mime-edit-enclose-region-internal 'pgp-encrypted beg end)
+  )
+
+(defun mime-edit-enclose-kazu-signed-region (beg end)
+  (interactive "*r")
+  (mime-edit-enclose-region-internal 'kazu-signed beg end)
+  )
+
+(defun mime-edit-enclose-kazu-encrypted-region (beg end)
+  (interactive "*r")
+  (mime-edit-enclose-region-internal 'kazu-encrypted beg end)
+  )
+
+(defun mime-edit-enclose-smime-signed-region (beg end)
+  (interactive "*r")
+  (mime-edit-enclose-region-internal 'smime-signed beg end)
+  )
+
+(defun mime-edit-enclose-smime-encrypted-region (beg end)
+  (interactive "*r")
+  (mime-edit-enclose-region-internal 'smime-encrypted beg end)
+  )
 
 (defun mime-edit-insert-key (&optional arg)
   "Insert a pgp public key."
   (interactive "P")
   (mime-edit-insert-tag "application" "pgp-keys")
   (mime-edit-define-encoding "7bit")
-  (funcall (pgp-function 'insert-key))
-  )
+  (pgg-insert-key)
+  (if (and (not (eobp))
+          (not (looking-at mime-edit-single-part-tag-regexp)))
+      (insert (mime-make-text-tag) "\n")))
 
 
 ;;; @ flag setting
@@ -2136,7 +2492,7 @@ and insert data encoded as ENCODING. [mime-edit.el]"
 (defun mime-edit-set-split (arg)
   (interactive
    (list
-    (y-or-n-p "Do you want to enable split?")
+    (y-or-n-p "Do you want to enable split? ")
     ))
   (setq mime-edit-split-message arg)
   (if arg
@@ -2155,8 +2511,6 @@ Optional TRANSFER-LEVEL is a number of transfer-level, 7 or 8."
        (setq mime-transfer-level 8)
       (setq mime-transfer-level 7)
       ))
-  (setq mime-edit-charset-default-encoding-alist
-       (mime-make-charset-default-encoding-alist mime-transfer-level))
   (message (format "Current transfer-level is %d bit"
                   mime-transfer-level))
   (setq mime-transfer-level-string
@@ -2178,74 +2532,74 @@ Optional TRANSFER-LEVEL is a number of transfer-level, 7 or 8."
 ;;; @ pgp
 ;;;
 
+(defvar mime-edit-pgp-processing nil)
+(make-variable-buffer-local 'mime-edit-pgp-processing)
+
 (defun mime-edit-set-sign (arg)
   (interactive
    (list
-    (y-or-n-p "Do you want to sign?")
+    (y-or-n-p "Do you want to sign? ")
     ))
   (if arg
-      (if mime-edit-signing-type
-         (progn
-           (setq mime-edit-pgp-processing 'sign)
-           (message "This message will be signed.")
-           )
-       (message "Please specify signing type.")
+      (progn
+       (or (memq 'sign mime-edit-pgp-processing)
+           (setq mime-edit-pgp-processing 
+                 (nconc mime-edit-pgp-processing 
+                        (copy-sequence '(sign)))))
+       (message "This message will be signed.")
        )
-    (if (eq mime-edit-pgp-processing 'sign)
-       (setq mime-edit-pgp-processing nil)
-      )
+    (setq mime-edit-pgp-processing 
+         (delq 'sign mime-edit-pgp-processing))
     (message "This message will not be signed.")
     ))
 
 (defun mime-edit-set-encrypt (arg)
   (interactive
    (list
-    (y-or-n-p "Do you want to encrypt?")
+    (y-or-n-p "Do you want to encrypt? ")
     ))
   (if arg
-      (if mime-edit-encrypting-type
-         (progn
-           (setq mime-edit-pgp-processing 'encrypt)
-           (message "This message will be encrypt.")
-           )
-       (message "Please specify encrypting type.")
+      (progn
+       (or (memq 'encrypt mime-edit-pgp-processing)
+           (setq mime-edit-pgp-processing 
+                 (nconc mime-edit-pgp-processing 
+                        (copy-sequence '(encrypt)))))
+       (message "This message will be encrypt.")
        )
-    (if (eq mime-edit-pgp-processing 'encrypt)
-       (setq mime-edit-pgp-processing nil)
-      )
+    (setq mime-edit-pgp-processing
+         (delq 'encrypt mime-edit-pgp-processing))
     (message "This message will not be encrypt.")
     ))
 
-(defvar mime-edit-pgp-processing nil)
-(make-variable-buffer-local 'mime-edit-pgp-processing)
-
 (defun mime-edit-pgp-enclose-buffer ()
   (let ((beg (save-excursion
               (goto-char (point-min))
               (if (search-forward (concat "\n" mail-header-separator "\n"))
                   (match-end 0)
                 )))
-       (end (point-max))
        )
     (if beg
-       (cond ((eq mime-edit-pgp-processing 'sign)
-              (mime-edit-enclose-signed-region beg end)
-              )
-             ((eq mime-edit-pgp-processing 'encrypt)
-              (mime-edit-enclose-encrypted-region beg end)
-              ))
+       (dolist (pgp-processing mime-edit-pgp-processing)
+         (case pgp-processing
+           (sign
+            (mime-edit-enclose-pgp-signed-region 
+             beg (point-max))
+            )
+           (encrypt
+            (mime-edit-enclose-pgp-encrypted-region 
+             beg (point-max))
+            )))
       )))
 
 
 ;;; @ split
 ;;;
 
-(defun mime-edit-insert-partial-header
-  (fields subject id number total separator)
+(defun mime-edit-insert-partial-header (fields subject
+                                              id number total separator)
   (insert fields)
   (insert (format "Subject: %s (%d/%d)\n" subject number total))
-  (insert (format "Mime-Version: 1.0 (split by %s)\n"
-                 mime-edit-version-name))
+  (insert mime-edit-mime-version-field-for-message/partial)
   (insert (format "\
 Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
                  id number total separator))
@@ -2263,11 +2617,7 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
            (or (cdr (assq major-mode mime-edit-message-max-lines-alist))
                mime-edit-message-default-max-lines))
       )
-  (let* ((mime-edit-draft-file-name 
-         (or (buffer-file-name)
-             (make-temp-name
-              (expand-file-name "mime-draft" mime/tmp-dir))))
-        (separator mail-header-separator)
+  (let* ((separator mail-header-separator)
         (id (concat "\""
                     (replace-space-with-underline (current-time-string))
                     "@" (system-name) "\"")))
@@ -2328,7 +2678,7 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
          (message (format "Sending %d/%d..."
                           mime-edit-partial-number total))
          (call-interactively command)
-         (message (format "Sending %d/%d... done"
+         (message (format "Sending %d/%d...done"
                           mime-edit-partial-number total))
          )
        (setq mime-edit-partial-number
@@ -2346,7 +2696,7 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
       (save-excursion
        (message (format "Sending %d/%d..."
                         mime-edit-partial-number total))
-       (message (format "Sending %d/%d... done"
+       (message (format "Sending %d/%d...done"
                         mime-edit-partial-number total))
        )
       )))
@@ -2371,7 +2721,7 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
 (defvar mime-edit-buffer nil) ; buffer local variable
 
 (defun mime-edit-preview-message ()
-  "preview editing MIME message. [mime-edit.el]"
+  "preview editing MIME message."
   (interactive)
   (let* ((str (buffer-string))
         (separator mail-header-separator)
@@ -2379,6 +2729,7 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
         (buf-name (buffer-name))
         (temp-buf-name (concat "*temp-article:" buf-name "*"))
         (buf (get-buffer temp-buf-name))
+        (pgp-processing mime-edit-pgp-processing)
         )
     (if buf
        (progn
@@ -2389,12 +2740,13 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
       (switch-to-buffer buf)
       )
     (insert str)
-    (setq major-mode 'mime/temporary-message-mode)
+    (setq major-mode 'mime-temp-message-mode)
     (make-local-variable 'mail-header-separator)
     (setq mail-header-separator separator)
     (make-local-variable 'mime-edit-buffer)
     (setq mime-edit-buffer the-buf)
-    
+    (setq mime-edit-pgp-processing pgp-processing)
+
     (run-hooks 'mime-edit-translate-hook)
     (mime-edit-translate-buffer)
     (goto-char (point-min))
@@ -2402,190 +2754,290 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
         (concat "^" (regexp-quote separator) "$"))
        (replace-match "")
       )
-    (mime-view-mode)
-    ))
+    (mime-view-buffer)
+    (make-local-variable 'mime-edit-temp-message-buffer)
+    (setq mime-edit-temp-message-buffer buf)))
 
 (defun mime-edit-quitting-method ()
-  (let ((temp mime::preview/article-buffer)
-       buf)
-    (mime-view-kill-buffer)
+  "Quitting method for mime-view."
+  (let* ((temp mime-edit-temp-message-buffer)
+        buf)
+    (mime-preview-kill-buffer)
     (set-buffer temp)
     (setq buf mime-edit-buffer)
     (kill-buffer temp)
-    (switch-to-buffer buf)
-    ))
+    (switch-to-buffer buf)))
 
-(set-alist 'mime-view-quitting-method-alist
-          'mime/temporary-message-mode
-          (function mime-edit-quitting-method)
-          )
+(set-alist 'mime-preview-quitting-method-alist
+          'mime-temp-message-mode
+          #'mime-edit-quitting-method)
 
 
 ;;; @ edit again
 ;;;
 
-(defun mime-editor::edit-again (code-conversion)
-  (save-excursion
-    (goto-char (point-min))
-    (let ((ctl (mime/Content-Type)))
-      (if ctl
-         (let ((ctype (car ctl))
-               (params (cdr ctl))
-               type stype)
-           (if (string-match "/" ctype)
-               (progn
-                 (setq type (substring ctype 0 (match-beginning 0)))
-                 (setq stype (substring ctype (match-end 0)))
-                 )
-             (setq type ctype)
-             )
-           (cond
-            ((string= ctype "application/pgp-signature")
-             (delete-region (point-min)(point-max))
-             )
-            ((string= type "multipart")
-             (let* ((boundary (cdr (assoc "boundary" params)))
-                    (boundary-pat
-                     (concat "\n--" (regexp-quote boundary) "[ \t]*\n"))
-                    )
-               (re-search-forward boundary-pat nil t)
-               (let ((bb (match-beginning 0)) eb tag)
-                 (setq tag (format "\n--<<%s>>-{\n" stype))
-                 (goto-char bb)
-                 (insert tag)
-                 (setq bb (+ bb (length tag)))
-                 (re-search-forward
-                  (concat "\n--" (regexp-quote boundary) "--[ \t]*\n")
-                  nil t)
-                 (setq eb (match-beginning 0))
-                 (replace-match (format "--}-<<%s>>\n" stype))
-                 (save-restriction
-                   (narrow-to-region bb eb)
-                   (goto-char (point-min))
-                   (while (re-search-forward boundary-pat nil t)
-                     (let ((beg (match-beginning 0))
-                           end)
-                       (delete-region beg (match-end 0))
-                       (save-excursion
-                         (if (re-search-forward boundary-pat nil t)
-                             (setq end (match-beginning 0))
-                           (setq end (point-max))
-                           )
-                         (save-restriction
-                           (narrow-to-region beg end)
-                           (mime-editor::edit-again code-conversion)
-                           (goto-char (point-max))
-                           ))))
-                   ))
-               (goto-char (point-min))
-               (or (= (point-min) 1)
-                   (delete-region (point-min)
+(defvar mime-edit-again-ignored-field-regexp
+  (concat "^\\(" "Content-.*\\|Mime-Version"
+         (if mime-edit-insert-user-agent-field "\\|User-Agent")
+         "\\):")
+  "Regexp for deleted header fields when `mime-edit-again' is called.")
+
+(defsubst eliminate-top-spaces (string)
+  "Eliminate top sequence of space or tab in STRING."
+  (if (string-match "^[ \t]+" string)
+      (substring string (match-end 0))
+    string))
+
+(defun mime-edit-decode-multipart-in-buffer (content-type not-decode-text)
+  (let* ((subtype
+         (or
+          (cdr (assoc (mime-content-type-parameter content-type "protocol")
+                      '(("application/pgp-encrypted" . pgp-encrypted)
+                        ("application/pgp-signature" . pgp-signed))))
+          (mime-content-type-subtype content-type)))
+        (boundary (mime-content-type-parameter content-type "boundary"))
+        (boundary-pat (concat "\n--" (regexp-quote boundary) "[ \t]*\n")))
+    (re-search-forward boundary-pat nil t)
+    (let ((bb (match-beginning 0)) eb tag)
+      (setq tag (format "\n--<<%s>>-{\n" subtype))
+      (goto-char bb)
+      (insert tag)
+      (setq bb (+ bb (length tag)))
+      (re-search-forward
+       (concat "\n--" (regexp-quote boundary) "--[ \t]*\n")
+       nil t)
+      (setq eb (match-beginning 0))
+      (replace-match (format "--}-<<%s>>\n" subtype))
+      (save-restriction
+       (narrow-to-region bb eb)
+       (goto-char (point-min))
+       (while (re-search-forward boundary-pat nil t)
+         (let ((beg (match-beginning 0))
+               end)
+           (delete-region beg (match-end 0))
+           (save-excursion
+             (if (re-search-forward boundary-pat nil t)
+                 (setq end (match-beginning 0))
+               (setq end (point-max))
+               )
+             (save-restriction
+               (narrow-to-region beg end)
+               (cond
+                ((eq subtype 'pgp-encrypted)
+                 (when (and
+                        (progn
+                          (goto-char (point-min))
+                          (re-search-forward "^-+BEGIN PGP MESSAGE-+$"
+                                             nil t))
+                        (prog1 
+                            (save-window-excursion
+                              (pgg-decrypt-region (match-beginning 0)
+                                                  (point-max)))
+                          (delete-region (point-min)(point-max))))
+                   (insert-buffer-substring pgg-output-buffer)
+                   (mime-edit-decode-message-in-buffer 
+                    nil not-decode-text)
+                   (delete-region (goto-char (point-min))
                                   (if (search-forward "\n\n" nil t)
                                       (match-end 0)
-                                    (point-min)
-                                    )))
-               ))
-            (t
-             (let* (charset
-                    (pstr
-                     (let ((bytes (+ 14 (length ctype))))
-                       (mapconcat (function
-                                   (lambda (attr)
-                                     (if (string-equal (car attr) "charset")
-                                         (progn
-                                           (setq charset (cdr attr))
-                                           "")
-                                       (let* ((str
-                                               (concat (car attr)
-                                                       "=" (cdr attr))
-                                               )
-                                              (bs (length str))
-                                              )
-                                         (setq bytes (+ bytes bs 2))
-                                         (if (< bytes 76)
-                                             (concat "; " str)
-                                           (setq bytes (+ bs 1))
-                                           (concat ";\n " str)
-                                           )
-                                         ))))
-                                  params "")))
-                    encoding
-                    encoded)
-               (save-excursion
-                 (if (re-search-forward
-                      "Content-Transfer-Encoding:" nil t)
-                     (let ((beg (match-beginning 0))
-                           (hbeg (match-end 0))
-                           (end (std11-field-end)))
-                       (setq encoding
-                             (eliminate-top-spaces
-                              (std11-unfold-string
-                               (buffer-substring hbeg end))))
-                       (if (or charset (string-equal type "text"))
-                           (progn
-                             (delete-region beg (1+ end))
-                             (goto-char (point-min))
-                             (if (search-forward "\n\n" nil t)
-                                 (progn
-                                   (mime-decode-region
-                                    (match-end 0)(point-max) encoding)
-                                   (setq encoded t
-                                         encoding nil)
-                                   )))))))
-               (if (or code-conversion encoded)
-                   (decode-mime-charset-region
-                    (point-min)(point-max)
-                    (or charset default-mime-charset))
-                 )
-               (let ((he
-                      (if (re-search-forward "^$" nil t)
+                                    (point-min)))
+                   (goto-char (point-max))
+                   ))
+                (t 
+                 (mime-edit-decode-message-in-buffer
+                  (if (eq subtype 'digest)
+                      (eval-when-compile
+                        (make-mime-content-type 'message 'rfc822))
+                    )
+                  not-decode-text)
+                 (goto-char (point-max))
+                 ))
+               ))))
+       ))
+    (goto-char (point-min))
+    (or (= (point-min) 1)
+       (delete-region (point-min)
+                      (if (search-forward "\n\n" nil t)
                           (match-end 0)
                         (point-min)
                         )))
-                 (if (= (point-min) 1)
+    ))
+
+(defun mime-edit-decode-single-part-in-buffer
+  (content-type not-decode-text &optional content-disposition)
+  (let* ((type (mime-content-type-primary-type content-type))
+        (subtype (mime-content-type-subtype content-type))
+        (ctype (format "%s/%s" type subtype))
+        charset
+        (pstr (let ((bytes (+ 14 (length ctype))))
+                (mapconcat (function
+                            (lambda (attr)
+                              (if (string= (car attr) "charset")
+                                  (progn
+                                    (setq charset (cdr attr))
+                                    "")
+                                (let* ((str (concat (car attr)
+                                                    "=" (cdr attr)))
+                                       (bs (length str)))
+                                  (setq bytes (+ bytes bs 2))
+                                  (if (< bytes 76)
+                                      (concat "; " str)
+                                    (setq bytes (+ bs 1))
+                                    (concat ";\n " str)
+                                    )
+                                  ))))
+                           (mime-content-type-parameters content-type) "")))
+        encoding
+        encoded
+        (limit (save-excursion
+                 (if (search-forward "\n\n" nil t)
+                     (1- (point)))))
+        (disposition-type
+         (mime-content-disposition-type content-disposition))
+        (disposition-str
+         (if disposition-type
+             (let ((bytes (+ 21 (length (format "%s" disposition-type)))))
+               (mapconcat (function
+                           (lambda (attr)
+                             (let* ((str (concat
+                                          (car attr)
+                                          "="
+                                          (if (string-equal "filename"
+                                                            (car attr))
+                                              (std11-wrap-as-quoted-string
+                                               (cdr attr))
+                                            (cdr attr))))
+                                    (bs (length str)))
+                               (setq bytes (+ bytes bs 2))
+                               (if (< bytes 76)
+                                   (concat "; " str)
+                                 (setq bytes (+ bs 1))
+                                 (concat ";\n " str)
+                                 )
+                               )))
+                          (mime-content-disposition-parameters
+                           content-disposition)
+                          ""))))
+        )
+    (if disposition-type
+       (setq pstr (format "%s\nContent-Disposition: %s%s"
+                          pstr disposition-type disposition-str))
+      )
+    (save-excursion
+      (if (re-search-forward
+          "^Content-Transfer-Encoding:" limit t)
+         (let ((beg (match-beginning 0))
+               (hbeg (match-end 0))
+               (end (std11-field-end limit)))
+           (setq encoding
+                 (downcase
+                  (eliminate-top-spaces
+                   (std11-unfold-string
+                    (buffer-substring hbeg end)))))
+           (if (or charset (eq type 'text))
+               (progn
+                 (delete-region beg (1+ end))
+                 (goto-char (point-min))
+                 (if (search-forward "\n\n" nil t)
                      (progn
-                       (goto-char he)
-                       (insert
-                        (concat "\n"
-                                (mime-create-tag
-                                 (concat type "/" stype pstr) encoding)))
-                       )
-                   (delete-region (point-min) he)
-                   (insert
+                       (mime-decode-region
+                        (match-end 0)(point-max) encoding)
+                       (setq encoded t
+                             encoding nil)
+                       )))))))
+    (if (and (eq type 'text)
+            (or encoded (not not-decode-text)))
+       (progn
+         (save-excursion
+           (goto-char (point-min))
+           (while (re-search-forward "\r\n" nil t)
+             (replace-match "\n")
+             ))
+         (decode-mime-charset-region (point-min)(point-max)
+                                     (or charset default-mime-charset))
+         ))
+    (let ((he (if (re-search-forward "^$" nil t)
+                 (match-end 0)
+               (point-min)
+               )))
+      (if (and (eq type 'text)
+              (eq subtype 'x-rot13-47-48))
+         (mule-caesar-region he (point-max))
+       )
+      (if (= (point-min) 1)
+         (progn
+           (goto-char he)
+           (insert
+            (concat "\n"
                     (mime-create-tag
-                     (concat type "/" stype pstr) encoding))
-                   ))
-               ))))
-       (if code-conversion
+                     (format "%s/%s%s" type subtype pstr)
+                     encoding)))
+           )
+       (delete-region (point-min) he)
+       (insert
+        (mime-create-tag (format "%s/%s%s" type subtype pstr)
+                         encoding))
+       ))
+    ))
+
+;;;###autoload
+(defun mime-edit-decode-message-in-buffer (&optional default-content-type
+                                                    not-decode-text)
+  (save-excursion
+    (goto-char (point-min))
+    (let ((ctl (or (mime-read-Content-Type)
+                  default-content-type)))
+      (if ctl
+         (let ((type (mime-content-type-primary-type ctl)))
+           (cond
+            ((and (eq type 'application)
+                  (eq (mime-content-type-subtype ctl) 'pgp-signature))
+             (delete-region (point-min)(point-max))
+             )
+            ((eq type 'multipart)
+             (mime-edit-decode-multipart-in-buffer ctl not-decode-text)
+             )
+            (t
+             (mime-edit-decode-single-part-in-buffer
+              ctl not-decode-text (mime-read-Content-Disposition))
+             )))
+       (or not-decode-text
            (decode-mime-charset-region (point-min) (point-max)
-                                       default-mime-charset)
-         )
-       ))))
+                                       default-mime-charset))
+       )
+      (if (= (point-min) 1)
+         (progn
+           (save-restriction
+             (std11-narrow-to-header)
+             (goto-char (point-min))
+             (while (re-search-forward
+                     mime-edit-again-ignored-field-regexp nil t)
+               (delete-region (match-beginning 0) (1+ (std11-field-end)))
+               ))
+           (mime-decode-header-in-buffer (not not-decode-text))
+           ))
+      )))
 
-(defun mime/edit-again (&optional code-conversion no-separator no-mode)
+;;;###autoload
+(defun mime-edit-again (&optional not-decode-text no-separator not-turn-on)
+  "Convert current buffer to MIME-Edit buffer and turn on MIME-Edit mode.
+Content-Type and Content-Transfer-Encoding header fields will be
+converted to MIME-Edit tags."
   (interactive)
-  (mime-editor::edit-again code-conversion)
   (goto-char (point-min))
-  (save-restriction
-    (narrow-to-region
-     (point-min)
-     (if (re-search-forward
-         (concat "^\\(" (regexp-quote mail-header-separator) "\\)?$")
-         nil t)
-        (match-end 0)
-       (point-max)
-       ))
-    (goto-char (point-min))
-    (while (re-search-forward
-           "^\\(Content-.*\\|Mime-Version\\):" nil t)
-      (delete-region (match-beginning 0) (1+ (std11-field-end)))
-      ))
+  (if (search-forward
+       (concat "\n" (regexp-quote mail-header-separator) "\n")
+       nil t)
+      (replace-match "\n\n")
+    )
+  (mime-edit-decode-message-in-buffer nil not-decode-text)
+  (goto-char (point-min))
   (or no-separator
       (and (re-search-forward "^$")
           (replace-match mail-header-separator)
           ))
-  (or no-mode
-      (mime-edit-mode)
+  (or not-turn-on
+      (turn-on-mime-edit)
       ))