Move definition of variable `mime-raw-representation-type' from
[elisp/semi.git] / mime-edit.el
index 1d7857c..4209551 100644 (file)
@@ -1,16 +1,15 @@
 ;;; mime-edit.el --- Simple MIME Composer for GNU Emacs
 
-;; Copyright (C) 1993,1994,1995,1996,1997 Free Software Foundation, Inc.
+;; Copyright (C) 1993,1994,1995,1996,1997,1998 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>
 ;; Created: 1994/08/21 renamed from mime.el
 ;;     Renamed: 1997/2/21 from tm-edit.el
-;; Version: $Revision: 0.67 $
 ;; 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
@@ -92,7 +91,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]]
 ;;; @ version
 ;;;
 
-(defconst mime-edit-RCS-ID
-  "$Id: mime-edit.el,v 0.67 1997-03-07 13:11:57 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))
+(defconst mime-edit-version-string
+  `,(concat (car mime-module-version) " "
+           (mapconcat #'number-to-string (cddr mime-module-version) ".")
+           " - \"" (cadr mime-module-version) "\""))
 
 
 ;;; @ variables
 ;;;
 
-(defvar mime-ignore-preceding-spaces nil
-  "*Ignore preceding white spaces if non-nil.")
+(defgroup mime-edit nil
+  "MIME edit mode"
+  :group 'mime)
+
+(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"
@@ -180,7 +196,7 @@ To insert a signature file automatically, call the function
      ("html"
       ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8")
       )
-     ("x-rot13-47")
+     ("x-rot13-47-48")
      )
     ("message"
      ("external-body"
@@ -209,6 +225,7 @@ To insert a signature file automatically, call the function
     ("image"
      ("gif")
      ("jpeg")
+     ("png")
      ("tiff")
      ("x-pic")
      ("x-mag")
@@ -220,8 +237,18 @@ To insert a signature file automatically, call the function
     )
   "*Alist of content-type, subtype, parameters and its values.")
 
-(defvar mime-file-types
-  '(("\\.rtf$"
+(defcustom mime-file-types
+  '(("\\.txt$"
+     "text"    "plain"         nil
+     nil
+     "inline"          (("filename" . file))
+     )
+    ("\\.pln$"
+     "text"    "plain"         nil
+     nil
+     "inline"          (("filename" . file))
+     )
+    ("\\.rtf$"
      "text"    "richtext"      nil
      nil
      nil               nil)
@@ -244,6 +271,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"
@@ -340,15 +372,56 @@ To insert a signature file automatically, call the function
      "attachment"      (("filename" . file))
      )
     ("\\.signature"
-     "text"    "plain"         nil     nil)
+     "text"    "plain"         nil     nil     nil     nil)
     (".*"
      "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 (car cell))
+                                    )
+                                  mime-file-encoding-method-alist)))
+               ;; 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
@@ -417,7 +490,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 "^"
@@ -431,20 +504,26 @@ 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]*$\\)")
@@ -458,10 +537,10 @@ If it is not specified for a major-mode,
 ;;;
 
 (defvar mime-edit-signing-type 'pgp-elkins
-  "*PGP signing type (pgp-elkins, pgp-kazu or nil). [mime-edit.el]")
+  "*PGP signing type (pgp-elkins, pgp-kazu or nil).")
 
 (defvar mime-edit-encrypting-type 'pgp-elkins
-  "*PGP encrypting type (pgp-elkins, pgp-kazu or nil). [mime-edit.el]")
+  "*PGP encrypting type (pgp-elkins, pgp-kazu or nil).")
 
 
 ;;; @@ about tag
@@ -512,17 +591,25 @@ If it is not specified for a major-mode,
   "*If non-nil, insert X-Emacs header field.")
 
 (defvar mime-edit-x-emacs-value
-  (if running-xemacs
-      (concat emacs-version
-             (if (featurep 'mule)
-                 " with mule"
-               " without mule"))
+  (if (featurep 'xemacs)
+      (concat 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))))
+         (concat "Emacs " ver
+                 (if enable-multibyte-characters
+                     (concat ", MULE " mule-version)
+                   " (with raw setting)")
+                 (if (featurep 'meadow)
+                     (concat ", " (Meadow-version))
+                   ))
+       ver)))
+  "Body of X-Emacs field.
+If variable `mime-edit-insert-x-emacs-field' is not nil, it is
+inserted into message header.")
 
 \f
 ;;; @ constants
@@ -533,9 +620,13 @@ 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-string ")")
   "MIME version number.")
 
+(defconst mime-edit-mime-version-field-for-message/partial
+  (concat "MIME-Version: 1.0 (split by " mime-edit-version-string ")\n")
+  "MIME version field for message/partial.")
+
 
 ;;; @ keymap and menu
 ;;;
@@ -543,37 +634,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)
 
-(defvar mime-edit-prefix "\C-c\C-x"
-  "*Keymap prefix for MIME-Edit commands.")
-
-(defvar mime-edit-map (make-sparse-keymap)
-  "Keymap for MIME commands.")
-
-(define-key mime-edit-map "\C-t"       'mime-edit-insert-text)
-(define-key mime-edit-map "\C-i"       'mime-edit-insert-file)
-(define-key mime-edit-map "\C-e"       'mime-edit-insert-external)
-(define-key mime-edit-map "\C-v"       'mime-edit-insert-voice)
-(define-key mime-edit-map "\C-y"       'mime-edit-insert-message)
-(define-key mime-edit-map "\C-m"       'mime-edit-insert-mail)
-(define-key mime-edit-map "\C-w"       'mime-edit-insert-signature)
-(define-key mime-edit-map "\C-s"       'mime-edit-insert-signature)
-(define-key mime-edit-map "\C-k"       'mime-edit-insert-key)
-(define-key mime-edit-map "t"          'mime-edit-insert-tag)
-(define-key mime-edit-map "a"          'mime-edit-enclose-alternative-region)
-(define-key mime-edit-map "p"          'mime-edit-enclose-parallel-region)
-(define-key mime-edit-map "m"          'mime-edit-enclose-mixed-region)
-(define-key mime-edit-map "d"          'mime-edit-enclose-digest-region)
-(define-key mime-edit-map "s"          'mime-edit-enclose-signed-region)
-(define-key mime-edit-map "e"          'mime-edit-enclose-encrypted-region)
-(define-key mime-edit-map "q"          'mime-edit-enclose-quote-region)
-(define-key mime-edit-map "7"          'mime-edit-set-transfer-level-7bit)
-(define-key mime-edit-map "8"          'mime-edit-set-transfer-level-8bit)
-(define-key mime-edit-map "/"          'mime-edit-set-split)
-(define-key mime-edit-map "v"          'mime-edit-set-sign)
-(define-key mime-edit-map "h"          'mime-edit-set-encrypt)
-(define-key mime-edit-map "\C-p"       'mime-edit-preview-message)
-(define-key mime-edit-map "\C-z"       'mime-edit-exit)
-(define-key mime-edit-map "?"          'mime-edit-help)
+(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-signed-region)
+(define-key mime-edit-mode-enclosure-map
+  "\C-e" 'mime-edit-enclose-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")
 
@@ -604,10 +717,6 @@ Tspecials means any character that matches with it in header must be quoted.")
     )
   "MIME-edit menubar entry.")
 
-(defvar mime-edit-mode-map (make-sparse-keymap)
-  "Keymap for MIME-Edit mode commands.")
-(define-key mime-edit-mode-map mime-edit-prefix mime-edit-map)
-
 (cond (running-xemacs
        ;; modified by Pekka Marjola <pema@iki.fi>
        ;;      1995/9/5 (c.f. [tm-en:69])
@@ -626,7 +735,7 @@ Tspecials means any character that matches with it in header must be quoted.")
                                  ))
                               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)
@@ -654,22 +763,6 @@ Tspecials means any character that matches with it in header must be quoted.")
               )
        ))
 
-(cond (running-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)
-       ))
-
 
 ;;; @ functions
 ;;;
@@ -817,6 +910,24 @@ User customizable variables (not documented all of them):
       (turn-on-mime-edit)
       )))
 
+
+(cond (running-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."
@@ -824,20 +935,20 @@ User customizable variables (not documented all of them):
   (if mime-edit-mode-flag
       (error "You are already editing a MIME message.")
     (setq mime-edit-mode-flag t)
-    
+
     ;; 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 for XEmacs.
     (if running-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
@@ -854,6 +965,7 @@ User customizable variables (not documented all of them):
 ;;;###autoload
 (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.
 With no argument encode a message in the buffer into MIME, otherwise
@@ -893,26 +1005,27 @@ 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" "richtext"))
+              (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."
@@ -1013,8 +1126,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)
@@ -1121,7 +1235,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.
@@ -1131,7 +1245,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.
@@ -1166,26 +1280,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."
@@ -1417,7 +1530,7 @@ 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
@@ -1573,8 +1686,9 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
            (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 (as-binary-process
+            (funcall (pgp-function 'mime-sign)
+                     (point-min)(point-max) nil nil pgp-boundary))
            (throw 'mime-edit-error 'pgp-error)
            )
        ))))
@@ -1775,7 +1889,7 @@ Content-Transfer-Encoding: 7bit
                 (insert mime-edit-x-emacs-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
@@ -1795,22 +1909,24 @@ Content-Transfer-Encoding: 7bit
        ))))
 
 (defun mime-edit-translate-single-part-tag (&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))
             )
        (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)
-         )
+       (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"))
+           (eword-encode-header)
+           ))
        t)))
 
 (defun mime-edit-translate-region (beg end &optional boundary multipart)
@@ -1905,12 +2021,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
@@ -1945,6 +2059,34 @@ Content-Transfer-Encoding: 7bit
                   )
              (encode-mime-charset-region beg (mime-edit-content-end)
                                          charset)
+             ;; 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)
+                     (replace-match
+                      (concat (buffer-substring (match-beginning 0)
+                                                (match-end 1)) "\r\n"))
+                     )))
+             (goto-char beg)
              (mime-encode-region beg (mime-edit-content-end) encoding)
              (mime-edit-define-encoding encoding)
              ))
@@ -1983,7 +2125,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)
@@ -2042,7 +2184,7 @@ 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)))
@@ -2061,40 +2203,40 @@ and insert data encoded as ENCODING. [mime-edit.el]"
 
 (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)
   (interactive "*r")
   (if mime-edit-signing-type
-      (mime-edit-enclose-region "signed" beg end)
+      (mime-edit-enclose-region-internal 'signed beg end)
     (message "Please specify signing type.")
     ))
 
 (defun mime-edit-enclose-encrypted-region (beg end)
   (interactive "*r")
   (if mime-edit-signing-type
-      (mime-edit-enclose-region "encrypted" beg end)
+      (mime-edit-enclose-region-internal 'encrypted beg end)
     (message "Please specify encrypting type.")
     ))
 
@@ -2113,7 +2255,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
@@ -2158,7 +2300,7 @@ Optional TRANSFER-LEVEL is a number of transfer-level, 7 or 8."
 (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
@@ -2177,7 +2319,7 @@ Optional TRANSFER-LEVEL is a number of transfer-level, 7 or 8."
 (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
@@ -2217,12 +2359,11 @@ Optional TRANSFER-LEVEL is a number of transfer-level, 7 or 8."
 ;;; @ 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))
@@ -2240,7 +2381,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 
+  (let* ((mime-edit-draft-file-name
          (or (buffer-file-name)
              (make-temp-name
               (expand-file-name "mime-draft" mime-temp-directory))))
@@ -2348,7 +2489,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)
@@ -2371,7 +2512,7 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
     (setq mail-header-separator separator)
     (make-local-variable 'mime-edit-buffer)
     (setq mime-edit-buffer the-buf)
-    
+
     (run-hooks 'mime-edit-translate-hook)
     (mime-edit-translate-buffer)
     (goto-char (point-min))
@@ -2383,44 +2524,43 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
     ))
 
 (defun mime-edit-quitting-method ()
-  (let ((temp mime::preview/article-buffer)
+  "Quitting method for mime-view."
+  (let ((temp mime-raw-buffer)
        buf)
-    (mime-view-kill-buffer)
+    (mime-preview-kill-buffer)
     (set-buffer temp)
     (setq buf mime-edit-buffer)
     (kill-buffer temp)
     (switch-to-buffer buf)
     ))
 
-(set-alist 'mime-view-quitting-method-alist
+(set-alist 'mime-preview-quitting-method-alist
           'mime-temp-message-mode
-          (function mime-edit-quitting-method)
-          )
+          #'mime-edit-quitting-method)
 
 
 ;;; @ edit again
 ;;;
 
-(defun mime-editor::edit-again (code-conversion)
+(defvar mime-edit-again-ignored-field-regexp
+  (concat "^\\(" "Content-.*\\|Mime-Version"
+         (if mime-edit-insert-x-emacs-field "\\|X-Emacs")
+         "\\):")
+  "Regexp for deleted header fields when `mime-edit-again' is called.")
+
+(defun mime-edit-decode-buffer (not-decode-text)
   (save-excursion
     (goto-char (point-min))
-    (let ((ctl (mime/Content-Type)))
+    (let ((ctl (mime-read-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)
-             )
+         (let ((type (mime-content-type-primary-type ctl))
+               (stype (mime-content-type-subtype ctl))
+               (params (mime-content-type-parameters ctl)))
            (cond
-            ((string= ctype "application/pgp-signature")
+            ((and (eq type 'application)(eq stype 'pgp-signature))
              (delete-region (point-min)(point-max))
              )
-            ((string= type "multipart")
+            ((eq type 'multipart)
              (let* ((boundary (cdr (assoc "boundary" params)))
                     (boundary-pat
                      (concat "\n--" (regexp-quote boundary) "[ \t]*\n"))
@@ -2450,7 +2590,7 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
                            )
                          (save-restriction
                            (narrow-to-region beg end)
-                           (mime-editor::edit-again code-conversion)
+                           (mime-edit-decode-buffer not-decode-text)
                            (goto-char (point-max))
                            ))))
                    ))
@@ -2463,12 +2603,13 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
                                     )))
                ))
             (t
-             (let* (charset
+             (let* ((ctype (format "%s/%s" type stype))
+                    charset
                     (pstr
                      (let ((bytes (+ 14 (length ctype))))
                        (mapconcat (function
                                    (lambda (attr)
-                                     (if (string-equal (car attr) "charset")
+                                     (if (string= (car attr) "charset")
                                          (progn
                                            (setq charset (cdr attr))
                                            "")
@@ -2498,7 +2639,7 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
                              (eliminate-top-spaces
                               (std11-unfold-string
                                (buffer-substring hbeg end))))
-                       (if (or charset (string-equal type "text"))
+                       (if (or charset (eq type 'text))
                            (progn
                              (delete-region beg (1+ end))
                              (goto-char (point-min))
@@ -2509,7 +2650,7 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
                                    (setq encoded t
                                          encoding nil)
                                    )))))))
-               (if (or code-conversion encoded)
+               (if (or encoded (not not-decode-text))
                    (decode-mime-charset-region
                     (point-min)(point-max)
                     (or charset default-mime-charset))
@@ -2525,46 +2666,46 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
                        (insert
                         (concat "\n"
                                 (mime-create-tag
-                                 (concat type "/" stype pstr) encoding)))
+                                 (format "%s/%s%s" type stype pstr)
+                                 encoding)))
                        )
                    (delete-region (point-min) he)
                    (insert
                     (mime-create-tag
-                     (concat type "/" stype pstr) encoding))
+                     (format "%s/%s%s" type stype pstr)
+                     encoding))
                    ))
                ))))
-       (if code-conversion
+       (or not-decode-text
            (decode-mime-charset-region (point-min) (point-max)
                                        default-mime-charset)
-         )
+           )
        ))))
 
-(defun mime-edit-again (&optional code-conversion no-separator no-mode)
+(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))
+  (if (search-forward
+       (concat "\n" (regexp-quote mail-header-separator) "\n")
+       nil t)
+      (replace-match "\n\n")
+    )
+  (mime-edit-decode-buffer not-decode-text)
   (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)
-       ))
+    (std11-narrow-to-header)
     (goto-char (point-min))
-    (while (re-search-forward
-           "^\\(Content-.*\\|Mime-Version\\):" nil t)
+    (while (re-search-forward mime-edit-again-ignored-field-regexp nil t)
       (delete-region (match-beginning 0) (1+ (std11-field-end)))
       ))
   (or no-separator
       (and (re-search-forward "^$")
           (replace-match mail-header-separator)
           ))
-  (or no-mode
+  (or not-turn-on
       (turn-on-mime-edit)
       ))