This commit was generated by cvs2svn to compensate for changes in r296,
[elisp/tm.git] / tm-edit.el
index 5aee31a..fcfbf70 100644 (file)
@@ -1,29 +1,31 @@
 ;;;
 ;;; tm-edit.el --- Simple MIME Composer for GNU Emacs
 ;;;
-
-;; Copyright (C) 1993 UMEDA Masanobu
-;; Copyright (C) 1994,1995 MORIOKA Tomohiko
-
-;; Author: UMEDA Masanobu <umerin@mse.kyutech.ac.jp>
-;;         MORIOKA Tomohiko <morioka@jaist.ac.jp>
-;; Keywords: mail, news, MIME, multimedia, multilingual
-
-;; This file is not part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;;; Copyright (C) 1993 UMEDA Masanobu
+;;; Copyright (C) 1994,1995 MORIOKA Tomohiko
+;;;
+;;; 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
+;;; Version: $Revision: 7.41 $
+;;; Keywords: mail, news, MIME, multimedia, multilingual
+;;;
+;;; This file is part of tm (Tools for MIME).
+;;;
+;;; This program is free software; you can redistribute it and/or
+;;; modify it under the terms of the GNU General Public License as
+;;; published by the Free Software Foundation; either version 2, or
+;;; (at your option) any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with This program.  If not, write to the Free Software
+;;; Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 
 ;;; Commentary:
 
@@ -48,7 +50,7 @@
 ;; definition to load mime/editor-mode automatically:
 ;;
 ;; (autoload 'mime/editor-mode "tm-edit"
-;;     "Minor mode for editing MIME message." t)
+;;           "Minor mode for editing MIME message." t)
 ;;
 ;; In case of Mail mode (includes VM mode), you need the following
 ;; hook definition:
 ;;
 ;;--[[audio/basic][base64]]^M...audio encoded in base64 comes here...
 
-;; LCD Archive Entry:
-;; mime|Masanobu UMEDA|umerin@mse.kyutech.ac.jp|
-;; Simple MIME Composer|
-;; $Date: 1995/11/11 12:48:30 $|$Revision: 7.23 $|~/misc/mime.el.Z|
-
 ;;; Code:
 
 (require 'sendmail)
 ;;;
 
 (defconst mime-editor/RCS-ID
-  "$Id: tm-edit.el,v 7.23 1995/11/11 12:48:30 morioka Exp $")
+  "$Id: tm-edit.el,v 7.41 1996/01/18 17:49:17 morioka Exp $")
 
 (defconst mime-editor/version (get-version-string mime-editor/RCS-ID))
 
@@ -152,19 +149,6 @@ If non-nil, the text tag is not inserted unless something different.")
 (defvar mime-auto-hide-body t
   "*Hide non-textual body encoded in base64 after insertion if non-nil.")
 
-(defvar mime-body-charset-chooser
-  (cond ((boundp 'NEMACS)
-        (function mime-body-charset-chooser-for-nemacs))
-       ((featurep 'mule)
-        (function mime-body-charset-chooser-for-mule))
-       ((string-match "^19\\." emacs-version)
-        (function mime-body-charset-chooser-for-emacs19))
-       (t                              ;ASCII only emacs
-        (function mime-body-charset-chooser-for-emacs18)))
-  "*Function to identify charset and encoding of a text in a given region.
-The value is a form of (CHARSET . ENCODING), where ENCODING must be a
-full name, such as base64.")
-
 (defvar mime-string-encoder
   (cond ((boundp 'NEMACS)
         (function mime-string-encoder-for-nemacs))
@@ -221,8 +205,12 @@ To insert a signature file specified by mime-signature-file
        ("site" "ftp.jaist.ac.jp" "wnoc-fuk.wide.ad.jp" "nic.karrn.ad.jp")
        ("directory" "/pub/GNU/elisp/mime")
        ("name")
-       ("mode" "binary" "ascii"))
-       ("ftp" ("site") ("directory") ("name") ("mode" "binary" "ascii"))
+       ("mode" "image" "ascii" "local8"))
+       ("ftp"
+       ("site")
+       ("directory")
+       ("name")
+       ("mode" "image" "ascii" "local8"))
        ("tftp"        ("site") ("name"))
        ("afs"         ("site") ("name"))
        ("local-file"  ("site") ("name"))
@@ -231,10 +219,7 @@ To insert a signature file specified by mime-signature-file
      ("rfc822")
      )
     ("application"
-     ("octet-stream"
-      ("name")
-      ("type" "" "tar" "shar")
-      ("conversions"))
+     ("octet-stream" ("type" "" "tar" "shar"))
      ("postscript")
      ("x-kiss" ("x-cnf")))
     ("image"
@@ -242,6 +227,7 @@ To insert a signature file specified by mime-signature-file
      ("jpeg")
      ("tiff")
      ("x-pic")
+     ("x-mag")
      ("x-xwd")
      ("x-xbm")
      )
@@ -252,47 +238,125 @@ To insert a signature file specified by mime-signature-file
 
 (defvar mime-file-types
   '(("\\.rtf$"
-     "text"    "richtext"      nil     nil)
+     "text"    "richtext"      nil
+     nil
+     nil               nil)
     ("\\.html$"
-     "text"    "html"          nil     nil)
+     "text"    "html"          nil
+     nil
+     nil               nil)
     ("\\.ps$"
-     "application" "postscript"        nil     "quoted-printable")
-    ("\\.gif$"
-     "image"   "gif"           nil     "base64"
-     (("Content-Description" . file))
+     "application" "postscript"        nil
+     "quoted-printable"
+     "attachment"      (("filename" . file))
      )
     ("\\.jpg$"
-     "image"   "jpeg"          nil     "base64")
-    ("\\.xwd$"
-     "image"   "x-xwd"         nil     "base64")
-    ("\\.xbm$"
-     "image"   "x-xbm"         nil     "base64")
-    ("\\.pic$"
-     "image"   "x-pic"         nil     "base64"
-     (("Content-Description" . file))
+     "image"   "jpeg"          nil
+     "base64"
+     "inline"          (("filename" . file))
+     )
+    ("\\.gif$"
+     "image"   "gif"           nil
+     "base64"
+     "inline"          (("filename" . file))
      )
     ("\\.tiff$"
-     "image"   "tiff"          nil     "base64")
+     "image"   "tiff"          nil
+     "base64"
+     "inline"          (("filename" . file))
+     )
+    ("\\.pic$"
+     "image"   "x-pic"         nil
+     "base64"
+     "inline"          (("filename" . file))
+     )
+    ("\\.mag$"
+     "image"   "x-mag"         nil
+     "base64"
+     "inline"          (("filename" . file))
+     )
+    ("\\.xbm$"
+     "image"   "x-xbm"         nil
+     "base64"
+     "inline"          (("filename" . file))
+     )
+    ("\\.xwd$"
+     "image"   "x-xwd"         nil
+     "base64"
+     "inline"          (("filename" . file))
+     )
     ("\\.au$"
-     "audio"   "basic"         nil     "base64")
+     "audio"   "basic"         nil
+     "base64"
+     "attachment"              (("filename" . file))
+     )
     ("\\.mpg$"
-     "video"   "mpeg"          nil     "base64")
+     "video"   "mpeg"          nil
+     "base64"
+     "attachment"      (("filename" . file))
+     )
     ("\\.el$"
-     "application" "octet-stream" (("name" . file)
-                                  ("type" . "emacs-lisp")) "7bit")
+     "application" "octet-stream" (("type" . "emacs-lisp"))
+     "7bit"
+     "attachment"      (("filename" . file))
+     )
     ("\\.lsp$"
-     "application" "octet-stream" (("name" . file)
-                                  ("type" . "common-lisp")) "7bit")
-    ("\\.tar.gz$"
-     "application" "octet-stream" (("name" . file)
-                                  ("type" . "tar")
-                                  ("conversions" . "gzip")) nil)
+     "application" "octet-stream" (("type" . "common-lisp"))
+     "7bit"
+     "attachment"      (("filename" . file))
+     )
+    ("\\.tar\\.gz$"
+     "application" "octet-stream" (("type" . "tar+gzip"))
+     nil
+     "attachment"      (("filename" . file))
+     )
+    ("\\.tgz$"
+     "application" "octet-stream" (("type" . "tar+gzip"))
+     nil
+     "attachment"      (("filename" . file))
+     )
+    ("\\.tar\\.Z$"
+     "application" "octet-stream" (("type" . "tar+compress"))
+     nil
+     "attachment"      (("filename" . file))
+     )
+    ("\\.taz$"
+     "application" "octet-stream" (("type" . "tar+compress"))
+     nil
+     "attachment"      (("filename" . file))
+     )
+    ("\\.gz$"
+     "application" "octet-stream" (("type" . "gzip"))
+     nil
+     "attachment"      (("filename" . file))
+     )
+    ("\\.Z$"
+     "application" "octet-stream" (("type" . "compress"))
+     nil
+     "attachment"      (("filename" . file))
+     )
+    ("\\.lzh$"
+     "application" "octet-stream" (("type" . "lha"))
+     nil
+     "attachment"      (("filename" . file))
+     )
+    ("\\.zip$"
+     "application" "zip" nil
+     nil
+     "attachment"      (("filename" . file))
+     )
     ("\\.diff$"
-     "application" "octet-stream" (("name" . file)
-                                  ("type" . "patch")) nil)
+     "application" "octet-stream" (("type" . "patch"))
+     nil
+     "attachment"      (("filename" . file))
+     )
     ("\\.signature"
      "text"    "plain"         nil     nil)
-    (".*"      nil             nil     nil     nil)
+    (".*"
+     "application" "octet-stream" nil
+     nil
+     "attachment"      (("filename" . file))
+     )
     )
   "*Alist of file name, types, parameters, and default encoding.
 If encoding is nil, it is determined from its contents.")
@@ -300,8 +364,16 @@ If encoding is nil, it is determined from its contents.")
 ;;; @@ about message inserting
 ;;;
 
-(defvar mime-editor/yank-ignored-fields-regexp
-  "^\\(Received\\|X-UIDL\\|Sender\\|Approved\\|Path\\):")
+(defvar mime-editor/yank-ignored-field-list
+  '("Received" "Sender" "Approved" "Path" "Status" "X-VM-.*" "X-UIDL")
+  "Delete these fields from original message when it is inserted
+as message/rfc822 part.
+Each elements are regexp of field-name. [tm-edit.el]")
+
+(defvar mime-editor/yank-ignored-field-regexp
+  (concat "^"
+         (apply (function regexp-or) mime-editor/yank-ignored-field-list)
+         ":"))
 
 (defvar mime-editor/message-inserter-alist nil)
 (defvar mime-editor/mail-inserter-alist nil)
@@ -309,17 +381,19 @@ If encoding is nil, it is determined from its contents.")
 ;;; @@ about message splitting
 ;;;
 
-(defvar mime-editor/split-message t)
+(defvar mime-editor/split-message t
+  "*Split large message if it is non-nil. [tm-edit.el]")
 
-(defvar mime-editor/message-default-max-length 1000)
+(defvar mime-editor/message-default-max-length 1000
+  "*Default maximum size of a message. [tm-edit.el]")
 
 (defvar mime-editor/message-max-length-alist
   '((news-reply-mode . 500)))
 
-(defconst mime-editor/split-ignored-fields-regexp
+(defconst mime-editor/split-ignored-field-regexp
   "\\(^Content-\\|^Subject:\\|^Mime-Version:\\)")
 
-(defvar mime-editor/split-blind-fields-regexp
+(defvar mime-editor/split-blind-field-regexp
   "\\(^[BDFbdf]cc:\\|^cc:[ \t]*$\\)")
 
 (defvar mime-editor/message-default-sender-alist
@@ -375,6 +449,21 @@ If encoding is nil, it is determined from its contents.")
 
 (defvar mime-editor/news-reply-mode-server-running nil)
 
+
+;;; @@ about PGP
+;;;
+
+(defvar mime-editor/signing-type nil
+  "*PGP signing type (pgp-elkins, pgp-kazu or nil). [tm-edit.el]")
+
+(defvar mime-editor/encrypting-type nil
+  "*PGP encrypting type (pgp-elkins, pgp-kazu or nil). [tm-edit.el]")
+
+(if (or mime-editor/signing-type mime-editor/encrypting-type)
+    (require 'mailcrypt)
+  )
+
+
 ;;; @@ about tag
 ;;;
 
@@ -452,11 +541,14 @@ Tspecials means any character that matches with it in header must be quoted.")
     (define-key keymap "\C-m" 'mime-editor/insert-mail)
     (define-key keymap "\C-w" 'mime-editor/insert-signature)
     (define-key keymap "\C-s" 'mime-editor/insert-signature)
+    (define-key keymap "\C-k" 'mime-editor/insert-key)
     (define-key keymap "t"    'mime-editor/insert-tag)
     (define-key keymap "a"    'mime-editor/enclose-alternative-region)
     (define-key keymap "p"    'mime-editor/enclose-parallel-region)
     (define-key keymap "m"    'mime-editor/enclose-mixed-region)
     (define-key keymap "d"    'mime-editor/enclose-digest-region)
+    (define-key keymap "s"    'mime-editor/enclose-signed-region)
+    (define-key keymap "e"    'mime-editor/enclose-encrypted-region)
     (define-key keymap "\C-p" 'mime-editor/preview-message)
     (define-key keymap "\C-z" 'mime-editor/exit)
     (define-key keymap "?"    'mime-editor/help)
@@ -465,22 +557,33 @@ Tspecials means any character that matches with it in header must be quoted.")
 (defconst mime-editor/menu-title "MIME-Edit")
 
 (defconst mime-editor/menu-list
-  '((mime-help "Describe MIME Mode"    mime-editor/help)
-    (file      "Insert File"           mime-editor/insert-file)
-    (external  "Insert External"       mime-editor/insert-external)
-    (voice     "Insert Voice"          mime-editor/insert-voice)
-    (message   "Insert Message"        mime-editor/insert-message)
-    (mail      "Insert Mail"           mime-editor/insert-mail)
-    (signature "Insert Signature"      mime-editor/insert-signature)
-    (text      "Insert Text"           mime-editor/insert-text)
-    (tag       "Insert Tag"            mime-editor/insert-tag)
-    (alternative "Enclose as alternative"
-                mime-editor/enclose-alternative-region)
-    (parallel  "Enclose as parallel"   mime-editor/enclose-parallel-region)
-    (mixed     "Enclose as serial"     mime-editor/enclose-mixed-region)
-    (digest    "Enclose as digest"     mime-editor/enclose-digest-region)
-    (preview   "Preview Message"       mime-editor/preview-message)
-    )
+  (nconc
+   '((mime-help        "Describe MIME editor mode" mime-editor/help)
+     (file     "Insert File"           mime-editor/insert-file)
+     (external "Insert External"       mime-editor/insert-external)
+     (voice    "Insert Voice"          mime-editor/insert-voice)
+     (message  "Insert Message"        mime-editor/insert-message)
+     (mail     "Insert Mail"           mime-editor/insert-mail)
+     (signature        "Insert Signature"      mime-editor/insert-signature)
+     (text     "Insert Text"           mime-editor/insert-text)
+     (tag      "Insert Tag"            mime-editor/insert-tag)
+     (alternative "Enclose as alternative"
+                 mime-editor/enclose-alternative-region)
+     (parallel "Enclose as parallel"   mime-editor/enclose-parallel-region)
+     (mixed    "Enclose as serial"     mime-editor/enclose-mixed-region)
+     (digest   "Enclose as digest"     mime-editor/enclose-digest-region)
+     (signed   "Enclose as signed"     mime-editor/enclose-signed-region)
+     (encrypted        "Enclose as encrypted"  mime-editor/enclose-encrypted-region)
+     (key      "Insert Public Key"     mime-editor/insert-key)
+     (split     "About split"           mime-editor/set-split)
+     )
+   (if (and (featurep 'mailcrypt)
+           (not (or mime-editor/signing-type mime-editor/encrypting-type)))
+       '((sign    "About sign"       mime-editor/set-sign)
+        (encrypt "About encryption" mime-editor/set-encrypt)
+        ))
+   '((preview  "Preview Message"       mime-editor/preview-message))
+   )
   "MIME-edit menubar entry.")
 
 (defun mime-editor/define-menu-for-emacs19 ()
@@ -499,7 +602,7 @@ Tspecials means any character that matches with it in header must be quoted.")
          ))
 
 ;;; modified by Pekka Marjola <pema@niksula.hut.fi>
-;;;    1995/9/5 (c.f. [tm-eng:69])
+;;;    1995/9/5 (c.f. [tm-en:69])
 (defun mime-editor/define-menu-for-xemacs ()
   "Define menu for Emacs 19."
   (cond ((featurep 'menubar)
@@ -514,6 +617,19 @@ Tspecials means any character that matches with it in header must be quoted.")
                                       ))
                                    mime-editor/menu-list)))
         )))
+
+;;; modified by Steven L. Baur <steve@miranova.com>
+;;;    1995/12/6 (c.f. [tm-en:209])
+(if (and (string-match "XEmacs\\|Lucid" emacs-version)
+        (not (boundp 'mime-editor/popup-menu-for-xemacs)))
+    (setq mime-editor/popup-menu-for-xemacs
+         (append '("MIME Commands" "---")
+                 (mapcar (function (lambda (item)
+                                     (vector (nth 1 item)
+                                             (nth 2 item)
+                                             t)))
+                         mime-editor/menu-list)))
+  )
 ;;; end
 
 
@@ -565,6 +681,9 @@ Following commands are available in addition to major mode commands:
 \\[mime-editor/enclose-parallel-region]        enclose as multipart/parallel.
 \\[mime-editor/enclose-mixed-region]   enclose as multipart/mixed.
 \\[mime-editor/enclose-digest-region]  enclose as multipart/digest.
+\\[mime-editor/enclose-signed-region]  enclose as PGP signed.
+\\[mime-editor/enclose-encrypted-region]       enclose as PGP encrypted.
+\\[mime-editor/insert-key]     insert PGP public key.
 \\[mime-editor/preview-message]        preview editing MIME message.
 \\[mime-editor/exit]   exit and translate into a MIME compliant message.
 \\[mime-editor/maybe-translate]        exit, translate and run the original command.
@@ -611,11 +730,6 @@ User customizable variables (not documented all of them):
     Hide a non-textual body message encoded in base64 after insertion
     if non-nil.
 
- mime-body-charset-chooser
-    Specifies a function to identify charset and encoding of a text in
-    a given region.  The value is a form of (CHARSET . ENCODING),
-    where ENCODING must be a full name, such as base64.
-
  mime-string-encoder
     Specifies a function to encode a string for given encoding method.
     The method is a form of (CHARSET . ENCODING).
@@ -668,9 +782,11 @@ User customizable variables (not documented all of them):
     (setq selective-display t)
     ;; I don't care about saving these.
     (setq paragraph-start
-         (concat mime-editor/single-part-tag-regexp "\\|" paragraph-start))
+         (regexp-or mime-editor/single-part-tag-regexp
+                    paragraph-start))
     (setq paragraph-separate
-         (concat mime-editor/single-part-tag-regexp "\\|" paragraph-separate))
+         (regexp-or mime-editor/single-part-tag-regexp
+                    paragraph-separate))
     (run-hooks 'mime/editor-mode-hook)
     (message
      (substitute-command-keys
@@ -718,7 +834,7 @@ just return to previous mode."
 (defun mime-editor/maybe-translate ()
   (interactive)
   (mime-editor/exit nil t)
-  (call-interactively 'mime-editor/split-and-send)
+  (call-interactively 'mime-editor/maybe-split-and-send)
   )
 
 (defun mime-editor/help ()
@@ -731,7 +847,7 @@ just return to previous mode."
 
 (defun mime-editor/insert-text ()
   "Insert a text message.
-Charset is automatically obtained from the mime-body-charset-chooser."
+Charset is automatically obtained from the `mime/lc-charset-alist'."
   (interactive)
   (if (and (mime-editor/insert-tag "text" nil nil)
           (looking-at mime-editor/single-part-tag-regexp))
@@ -749,7 +865,8 @@ Charset is automatically obtained from the mime-body-charset-chooser."
          (subtype (nth 1 guess))
          (parameters (nth 2 guess))
          (default (nth 3 guess))       ;Guess encoding from its file name.
-         (fields (nth 4 guess))
+         (disposition-type (nth 4 guess))
+         (disposition-params (nth 5 guess))
          (encoding
           (if (not (interactive-p))
               default
@@ -766,7 +883,7 @@ Charset is automatically obtained from the mime-body-charset-chooser."
              mime-encoding-method-alist nil t nil))))
     (if (string-equal encoding "")
        (setq encoding default))
-    (if (or (consp parameters) (consp fields))
+    (if (or (consp parameters) (stringp disposition-type))
        (let ((rest parameters) cell attribute value)
          (setq parameters "")
          (while rest
@@ -774,22 +891,31 @@ Charset is automatically obtained from the mime-body-charset-chooser."
            (setq attribute (car cell))
            (setq value (cdr cell))
            (if (eq value 'file)
-               (setq value (file-name-nondirectory file))
+               (setq value (rfc822/wrap-as-quoted-string
+                            (file-name-nondirectory file)))
              )
            (setq parameters (concat parameters "; " attribute "=" value))
            (setq rest (cdr rest))
            )
-         (setq rest fields)
-         (while rest
-           (setq cell (car rest))
-           (setq attribute (car cell))
-           (setq value (cdr cell))
-           (if (eq value 'file)
-               (setq value (file-name-nondirectory file))
-             )
-           (setq parameters (concat parameters "\n" attribute ": " value))
-           (setq rest (cdr rest))
-           )
+         (if disposition-type
+             (progn
+               (setq parameters
+                     (concat parameters "\n"
+                             "Content-Disposition: " disposition-type))
+               (setq rest disposition-params)
+               (while rest
+                 (setq cell (car rest))
+                 (setq attribute (car cell))
+                 (setq value (cdr cell))
+                 (if (eq value 'file)
+                     (setq value (rfc822/wrap-as-quoted-string
+                                  (file-name-nondirectory file)))
+                   )
+                 (setq parameters
+                       (concat parameters "; " attribute "=" value))
+                 (setq rest (cdr rest))
+                 )
+               ))
          ))
     (mime-editor/insert-tag pritype subtype parameters)
     (mime-editor/insert-binary-file file encoding)
@@ -823,16 +949,34 @@ Charset is automatically obtained from the mime-body-charset-chooser."
       (kill-buffer buffer)
       )))
 
-(defun mime-editor/insert-signature ()
+(defun mime-editor/insert-signature (&optional arg)
   "Insert a signature file specified by mime-signature-file."
-  (interactive)
-  (save-restriction
+  (interactive "P")
+  (let ((signature
+        (expand-file-name
+         (if arg
+             (read-file-name "Insert your signature: "
+                             (concat signature-file-name "-")
+                             signature-file-name
+                             nil)
+           (signature/get-signature-file-name))))
+       )
+    (if signature-insert-at-eof
+       (goto-char (point-max))
+      )
     (apply (function mime-editor/insert-tag)
-          (prog1
-              (mime-find-file-type (insert-signature))
-            (narrow-to-region (point-min)(point))
-            ))
-    ))
+          (mime-find-file-type signature))
+    (if (file-readable-p signature)
+       (progn
+         (goto-char (point-max))
+         (if (not (bolp))
+             (insert "\n"))
+         (delete-blank-lines)
+         (insert-file-contents signature)
+         (set-buffer-modified-p (buffer-modified-p))
+                                       ; force mode line update
+         ))))
+
 \f
 ;; Insert a new tag around a point.
 
@@ -842,7 +986,8 @@ If nothing is inserted, return nil."
   (interactive)
   (let ((oldtag nil)
        (newtag nil)
-       (current (point)))
+       (current (point))
+       exist-prev-tag exist-next-tag)
     (setq pritype
          (or pritype
              (mime-prompt-for-type)))
@@ -858,7 +1003,13 @@ If nothing is inserted, return nil."
     (setq oldtag
          (save-excursion
            (if (mime-editor/goto-tag)
-               (buffer-substring (match-beginning 0) (match-end 0))
+               (progn
+                 (if (eq current (match-beginning 0))
+                     (setq exist-next-tag t)
+                   (setq exist-prev-tag t)
+                   )
+                 (buffer-substring (match-beginning 0) (match-end 0))
+                 )
              ;; Assume content type is 'text/plan'.
              (mime-make-tag "text" "plain")
              )))
@@ -867,37 +1018,15 @@ If nothing is inserted, return nil."
             (not (mime-test-content-type
                   (mime-editor/get-contype oldtag) "text")))
        (setq oldtag nil))
-    (beginning-of-line)
-    (cond ((and oldtag                 ;Text
-               (not (eobp))
-               (save-excursion
-                 (forward-line -1)
-                 (looking-at mime-editor/beginning-tag-regexp)
-                 )
-               (or mime-ignore-same-text-tag
-                   (not (string-equal oldtag newtag))))
-          ;; If point is at the next of current tag, move to the
-          ;; beginning of the tag to disable insertion of extra tag.
-          (forward-line -1))
-         ((and oldtag                  ;Text
-               (not (eobp))
-               (not (looking-at mime-editor/tag-regexp))
-               (or mime-ignore-same-text-tag
-                   (not (string-equal oldtag newtag))))
-          ;; Copy current tag to break a text into two.
-          (save-excursion
-            (insert oldtag "\n")))
-         ((and (null oldtag)           ;Not text
-               (not (looking-at mime-editor/tag-regexp)))
-          ;; Adjust insertion point.  In the middle of text, it is
-          ;; okay to break the text into two.  However, it should not
-          ;; be broken into two, if otherwise.
-          (goto-char (mime-editor/content-end))
-          (if (eolp)
-              (forward-line 1))
-          (if (not (bolp))
-              (insert "\n"))
-          ))
+    (cond (exist-prev-tag (insert "\n"))
+         (exist-next-tag (save-excursion
+                           (insert "\n")
+                           )))
+    (if (not (bolp))
+       (if exist-prev-tag
+           (forward-line 1)
+         (insert "\n")
+         ))
     ;; Make a new tag.
     (if (or (not oldtag)               ;Not text
            (or mime-ignore-same-text-tag
@@ -1081,17 +1210,8 @@ Optional argument ENCODING specifies an encoding method such as base64."
 
 (defun mime-editor/choose-charset ()
   "Choose charset of a text following current point."
-  (save-excursion
-    (let* ((beg (point))
-          (end (mime-editor/content-end)))
-      (car (funcall mime-body-charset-chooser beg end)))))
-
-(defun mime-editor/choose-encoding ()
-  "Choose encoding of a text following current point."
-  (save-excursion
-    (let* ((beg (point))
-          (end (mime-editor/content-end)))
-      (cdr (funcall mime-body-charset-chooser beg end)))))
+  (mime/find-charset-region (point) (mime-editor/content-end))
+  )
 
 (defun mime-make-text-tag (&optional subtype)
   "Make a tag for a text after current point.
@@ -1320,26 +1440,343 @@ while if FLAG is `\\^M' (control-M) the text is hidden."
       (set-buffer-modified-p modp))))
 
 \f
-;; Translate the tagged MIME messages into a MIME compliant message.
+;;; @ Translate the tagged MIME messages into a MIME compliant message.
+;;;
 
 (defun mime-editor/translate-buffer ()
   "Encode the tagged MIME message in current buffer in MIME compliant message."
   (interactive)
-  (mime/encode-message-header)
-  (mime-editor/translate-body)
-  )
+  (if (catch 'mime-editor/error
+       (save-excursion
+         (mime/encode-message-header)
+         (mime-editor/translate-body)
+         (mime-editor/pgp-processing)
+         ))
+      (progn
+       (undo)
+       (error "Translation error!")
+       )))
+
+(defun mime-editor/find-inmost ()
+  (goto-char (point-min))
+  (if (re-search-forward mime-editor/multipart-beginning-regexp nil t)
+      (let ((bb (match-beginning 0))
+           (be (match-end 0))
+           (type (buffer-substring (match-beginning 1)(match-end 1)))
+           end-exp eb ee)
+       (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 (point-max))
+         (setq ee (point-max))
+         )
+       (narrow-to-region be eb)
+       (goto-char be)
+       (if (re-search-forward mime-editor/multipart-beginning-regexp nil t)
+           (let (ret)
+             (narrow-to-region (match-beginning 0)(point-max))
+             (mime-editor/find-inmost)
+             )
+         (widen)
+         ;;(delete-region eb ee)
+         (list type bb be eb)
+         ))))
+
+(defun mime-editor/process-multipart-1 (boundary)
+  (let ((ret (mime-editor/find-inmost)))
+    (if ret
+       (let ((type (car ret))
+             (bb (nth 1 ret))(be (nth 2 ret))
+             (eb (nth 3 ret))
+             )
+         (narrow-to-region bb eb)
+         (delete-region bb be)
+         (setq bb (point-min))
+         (setq eb (point-max))
+         (widen)
+         (goto-char eb)
+         (if (looking-at mime-editor/multipart-end-regexp)
+             (let ((beg (match-beginning 0))
+                   (end (match-end 0))
+                   )
+               (delete-region beg end)
+               (if (and (not (looking-at mime-editor/single-part-tag-regexp))
+                        (not (eobp)))
+                   (insert (concat (mime-make-text-tag) "\n"))
+                 )))
+         (cond ((string= type "signed")
+                (cond ((eq mime-editor/signing-type 'pgp-elkins)
+                       (mime-editor/sign-pgp-elkins bb eb boundary)
+                       )
+                      ((eq mime-editor/signing-type 'pgp-kazu)
+                       (mime-editor/process-pgp-kazu 'mc-sign
+                                                     bb eb boundary)
+                       )
+                      ))
+               ((string= type "encrypted")
+                (cond ((eq mime-editor/signing-type 'pgp-elkins)
+                       (mime-editor/encrypt-pgp-elkins bb eb boundary)
+                       )
+                      ((eq mime-editor/signing-type 'pgp-kazu)
+                       (mime-editor/process-pgp-kazu 'mc-encrypt
+                                                     bb eb boundary)
+                       )))
+               (t
+                (setq boundary
+                      (nth 2 (mime-editor/translate-region bb eb
+                                                           boundary t)))
+                (goto-char bb)
+                (insert
+                 (format "--[[multipart/%s;
+ boundary=\"%s\"][7bit]]\n"
+                         type boundary))
+                ))
+         boundary))))
+
+(defun tm:mc-pgp-generic-parser (result)
+  (let ((ret (mc-pgp-generic-parser result)))
+    (if (consp ret)
+       (vector (car ret)(cdr ret))
+      )))
+
+(autoload 'mc-pgp-lookup-key "mc-pgp")
+
+(defun tm:mc-process-region
+  (beg end passwd program args parser &optional buffer boundary)
+  (let ((obuf (current-buffer))
+       (process-connection-type nil)
+       mybuf result rgn proc)
+    (unwind-protect
+       (progn
+         (setq mybuf (or buffer (generate-new-buffer " *mailcrypt temp")))
+         (set-buffer mybuf)
+         (erase-buffer)
+         (set-buffer obuf)
+         (buffer-disable-undo mybuf)
+         (setq proc
+               (apply 'start-process "*PGP*" mybuf program args))
+         (if passwd
+             (progn
+               (process-send-string proc (concat passwd "\n"))
+               (or mc-passwd-timeout (mc-deactivate-passwd t))))
+         (process-send-region proc beg end)
+         (process-send-eof proc)
+         (while (eq 'run (process-status proc))
+           (accept-process-output proc 5))
+         (setq result (process-exit-status proc))
+         ;; Hack to force a status_notify() in Emacs 19.29
+         (delete-process proc)
+         (set-buffer mybuf)
+         (goto-char (point-max))
+         (if (re-search-backward "\nProcess \\*PGP.*\n\\'" nil t)
+             (delete-region (match-beginning 0) (match-end 0)))
+         (goto-char (point-min))
+         ;; CRNL -> NL
+         (while (search-forward "\r\n" nil t)
+           (replace-match "\n"))
+         ;; Hurm.  FIXME; must get better result codes.
+         (if (stringp result)
+             (error "%s exited abnormally: '%s'" program result)
+           (setq rgn (funcall parser result))
+           ;; If the parser found something, migrate it
+           (if (consp rgn)
+               (progn
+                 (set-buffer obuf)
+                 (if boundary
+                     (save-restriction
+                       (narrow-to-region beg end)
+                       (goto-char beg)
+                       (insert (format "--%s\n" boundary))
+                       (goto-char (point-max))
+                       (insert (format "\n--%s
+Content-Type: application/pgp-signature
+Content-Transfer-Encoding: 7bit
+
+" boundary))
+                       (insert-buffer-substring mybuf (car rgn) (cdr rgn))
+                       (goto-char (point-max))
+                       (insert (format "\n--%s--\n" boundary))
+                       )
+                   (delete-region beg end)
+                   (goto-char beg)
+                   (insert-buffer-substring mybuf (car rgn) (cdr rgn))
+                   )
+                 (set-buffer mybuf)
+                 (delete-region (car rgn) (cdr rgn)))))
+         ;; Return nil on failure and exit code on success
+         (if rgn result))
+      ;; Cleanup even on nonlocal exit
+      (if (and proc (eq 'run (process-status proc)))
+         (interrupt-process proc))
+      (set-buffer obuf)
+      (or buffer (null mybuf) (kill-buffer mybuf)))))
+
+(defun tm:mc-pgp-sign-region (start end &optional id unclear boundary)
+  (if (not (boundp 'mc-pgp-user-id))
+      (load "mc-pgp")
+    )
+  (let ((process-environment process-environment)
+       (buffer (get-buffer-create mc-buffer-name))
+       passwd args key
+       (parser (function mc-pgp-generic-parser))
+       (pgp-path mc-pgp-path)
+       )
+    (setq key (mc-pgp-lookup-key (or id mc-pgp-user-id)))
+    (setq passwd
+         (mc-activate-passwd
+          (cdr key)
+          (format "PGP passphrase for %s (%s): " (car key) (cdr key))))
+    (setenv "PGPPASSFD" "0")
+    (setq args
+         (cons
+          (if boundary
+              "-fbast"
+            "-fast")
+          (list "+verbose=1" "+language=en"
+                (format "+clearsig=%s" (if unclear "off" "on"))
+                "+batchmode" "-u" (cdr key))))
+    (if mc-pgp-comment
+       (setq args (cons (format "+comment=%s" mc-pgp-comment) args))
+      )
+    (message "Signing as %s ..." (car key))
+    (if (tm:mc-process-region
+        start end passwd pgp-path args parser buffer boundary)
+       (progn
+         (if boundary
+             (progn
+               (goto-char (point-min))
+               (insert
+                (format "\
+--[[multipart/signed; protocol=\"application/pgp-signature\";
+ boundary=\"%s\"; micalg=pgp-md5][7bit]]\n" boundary))
+               ))
+         (message "Signing as %s ... Done." (car key))
+         t)
+      nil)))
+
+(defun mime-editor/sign-pgp-elkins (beg end boundary)
+  (save-excursion
+    (save-restriction
+      (narrow-to-region beg end)
+      (let* ((ret
+             (mime-editor/translate-region beg end boundary))
+            (ctype    (car ret))
+            (encoding (nth 1 ret))
+            (parts    (nth 3 ret))
+            (pgp-boundary (concat "pgp-sign-" boundary))
+            )
+       (goto-char beg)
+       (insert (format "Content-Type: %s\n" ctype))
+       (if encoding
+           (insert (format "Content-Transfer-Encoding: %s\n" encoding))
+         )
+       (insert "\n")
+       (or (tm:mc-pgp-sign-region (point-min)(point-max)
+                                  nil nil pgp-boundary)
+           (throw 'mime-editor/error 'pgp-error)
+           )
+       ))))
+
+(defun mime-editor/encrypt-pgp-elkins (beg end boundary)
+  (save-excursion
+    (save-restriction
+      (narrow-to-region beg end)
+      (let* ((ret
+             (mime-editor/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 (format "Content-Type: %s\n" ctype))
+       (if encoding
+           (insert (format "Content-Transfer-Encoding: %s\n" encoding))
+         )
+       (insert "\n")
+       (if (null
+            (progn
+              (goto-char beg)
+              (insert "=\n")
+              (prog1
+                  (let ((mail-header-separator "="))
+                    (call-interactively 'mc-encrypt)
+                    )
+                (goto-char beg)
+                (and (search-forward "=\n")
+                     (replace-match ""))
+                )))
+           (throw 'mime-editor/error 'pgp-error)
+         )
+       (goto-char beg)
+       (insert (format "--[[multipart/encrypted;
+ boundary=\"%s\";
+ protocol=\"application/pgp-encrypted\"][7bit]]
+--%s
+Content-Type: application/pgp-encrypted
+
+--%s
+Content-Type: application/octet-stream
+Content-Transfer-Encoding: 7bit
+
+" pgp-boundary pgp-boundary pgp-boundary))
+       (goto-char (point-max))
+       (insert (format "\n--%s--\n" pgp-boundary))
+       ))
+    ))
+
+(defun mime-editor/process-pgp-kazu (type beg end boundary)
+  (save-excursion
+    (save-restriction
+      (narrow-to-region beg end)
+      (let* ((ret
+             (mime-editor/translate-region beg end boundary))
+            (ctype    (car ret))
+            (encoding (nth 1 ret))
+            (parts    (nth 3 ret))
+            )
+       (goto-char beg)
+       (insert (format "Content-Type: %s\n" ctype))
+       (if encoding
+           (insert (format "Content-Transfer-Encoding: %s\n" encoding))
+         )
+       (insert "\n")
+       (if (null
+            (progn
+              (goto-char beg)
+              (insert "=\n")
+              (prog1
+                  (let ((mail-header-separator "="))
+                    (call-interactively type)
+                    )
+                (goto-char beg)
+                (and (search-forward "=\n")
+                     (replace-match ""))
+                )))
+           (throw 'mime-editor/error 'pgp-error)
+         )
+       (goto-char beg)
+       (insert
+        "--[[application/pgp; format=mime][7bit]]\n")
+       ))
+    ))
 
 (defun mime-editor/translate-body ()
   "Encode the tagged MIME body in current buffer in MIME compliant message."
   (interactive)
   (save-excursion
     (let ((boundary
-          (concat mime-multipart-boundary " " (current-time-string)))
+          (concat mime-multipart-boundary "_"
+                  (replace-space-with-underline (current-time-string))
+                  ))
          (i 1)
-         (time (current-time-string))
          ret)
       (while (mime-editor/process-multipart-1
-             (format "%s %s-%d" mime-multipart-boundary time i))
+             (format "%s-%d" boundary i))
        (setq i (1+ i))
        )
       (save-restriction
@@ -1361,7 +1798,7 @@ while if FLAG is `\\^M' (control-M) the text is hidden."
                  (point))))
          (setq ret (mime-editor/translate-region
                     beg end
-                    (format "%s %s-%d" mime-multipart-boundary time i)))
+                    (format "%s-%d" boundary i)))
          ))
       (let ((contype (car ret))                ;Content-Type
            (encoding (nth 1 ret))      ;Content-Transfer-Encoding
@@ -1386,6 +1823,70 @@ while if FLAG is `\\^M' (control-M) the text is hidden."
              (insert encoding)))
        ))))
 
+(defun mime-editor/translate-region (beg end &optional boundary multipart)
+  (if (null boundary)
+      (setq boundary
+           (concat mime-multipart-boundary "_"
+                   (replace-space-with-underline (current-time-string))))
+    )
+  (save-excursion
+    (save-restriction
+      (narrow-to-region beg end)
+      (let ((tag nil)                  ;MIME tag
+           (contype nil)               ;Content-Type
+           (encoding nil)              ;Content-Transfer-Encoding
+           (nparts 0))                 ;Number of body parts
+       ;; Normalize the body part by inserting appropriate message
+       ;; tags for every message contents.
+       (mime-editor/normalize-body)
+       ;; Counting the number of Content-Type.
+       (goto-char (point-min))
+       (while (re-search-forward mime-editor/single-part-tag-regexp nil t)
+         (setq nparts (1+ nparts)))
+       ;; Begin translation.
+       (cond ((and (<= nparts 1)(not multipart))
+              ;; It's a singular message.
+              (goto-char (point-min))
+              (while (re-search-forward
+                      mime-editor/single-part-tag-regexp nil t)
+                (setq tag
+                      (buffer-substring (match-beginning 0) (match-end 0)))
+                (delete-region (match-beginning 0) (1+ (match-end 0)))
+                (setq contype (mime-editor/get-contype tag))
+                (setq encoding (mime-editor/get-encoding tag))
+                ))
+             (t
+              ;; It's a multipart message.
+              (goto-char (point-min))
+              (while (re-search-forward
+                      mime-editor/single-part-tag-regexp nil t)
+                (setq tag
+                      (buffer-substring (match-beginning 0) (match-end 0)))
+                (delete-region (match-beginning 0) (match-end 0))
+                (setq contype (mime-editor/get-contype tag))
+                (setq encoding (mime-editor/get-encoding tag))
+                (insert "--" boundary "\n")
+                (insert "Content-Type: " contype "\n")
+                (if encoding
+                    (insert "Content-Transfer-Encoding: " encoding "\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))
+              (if multipart
+                  (insert "--" boundary "--\n")
+                (insert "\n--" boundary "--\n")
+                )))
+       (list contype encoding boundary nparts)
+       ))))
+
 (defun mime-editor/normalize-body ()
   "Normalize the body part by inserting appropriate message tags."
   ;; Insert the first MIME tags if necessary.
@@ -1434,7 +1935,10 @@ while if FLAG is `\\^M' (control-M) the text is hidden."
             ;; Point is now on current tag.
             ;; Define encoding and encode text if necessary.
             (if (null encoding)        ;Encoding is not specified.
-                (let* ((encoding (mime-editor/choose-encoding))
+                (let* ((encoding
+                        (cdr
+                         (assoc charset mime/charset-default-encoding-alist)
+                         ))
                        (beg (mime-editor/content-beginning))
                        (end (mime-editor/content-end))
                        (body (buffer-substring beg end))
@@ -1485,12 +1989,6 @@ while if FLAG is `\\^M' (control-M) the text is hidden."
 
 ;; Emacs 18 implementations
 
-(defun mime-body-charset-chooser-for-emacs18 (begin end)
-  "Return a cons of charset and encoding of a message in a given region.
-Encoding name must be a canonical name, such as `base64'."
-  '("US-ASCII" . nil)                  ;Default charset of MIME.
-  )
-
 (defun mime-string-encoder-for-emacs18 (method string)
   "For given METHOD that is a cons of charset and encoding, encode a STRING."
   (let ((charset (car method))
@@ -1504,18 +2002,6 @@ Encoding name must be a canonical name, such as `base64'."
 \f
 ;; Emacs 19 implementations
 
-(defun mime-body-charset-chooser-for-emacs19 (begin end)
-  "Return a cons of charset and encoding of a message in a given region.
-Encoding name must be a canonical name, such as `base64'.
-US-ASCII and ISO-8859-1 are supported on Emacs 19."
-  (cond ((save-excursion
-          (goto-char begin)
-          (re-search-forward "[\200-\377]" end t))
-        '("ISO-8859-1" . "quoted-printable"))
-       (t
-        '("US-ASCII" . nil))           ;Default charset of MIME.
-       ))
-
 (defun mime-string-encoder-for-emacs19 (method string)
   "For given METHOD that is a cons of charset and encoding, encode a STRING."
   (let ((charset (car method))
@@ -1529,22 +2015,6 @@ US-ASCII and ISO-8859-1 are supported on Emacs 19."
 \f
 ;; NEmacs implementations
 
-(defun mime-body-charset-chooser-for-nemacs (begin end)
-  "Return a cons of charset and encoding of a message in a given region.
-Encoding name must be a canonical name, such as `base64'.
-US-ASCII and ISO-2022-JP are supported on NEmacs."
-  (cond ((check-region-kanji-code begin end)
-        ;; The following are safe encoding methods for use in
-        ;; USENET News systems that strip off all ESCs.
-        ;; '("ISO-2022-JP" . "quoted-printable")
-        ;; '("ISO-2022-JP" . "base64")
-        ;; The following expects transport systems are all MIME
-        ;; compliants.  For instance, ESCs are never stripped off.
-        '("ISO-2022-JP" . nil))
-       (t
-        '("US-ASCII" . nil))           ;Default charset of MIME.
-       ))
-
 (defun mime-string-encoder-for-nemacs (method string)
   "For given METHOD that is a cons of charset and encoding, encode a STRING.
 US-ASCII and ISO-2022-JP are supported on NEmacs."
@@ -1568,50 +2038,6 @@ US-ASCII and ISO-2022-JP are supported on NEmacs."
 ;; Thanks to contributions by wkenji@flab.fujitsu.co.jp (Kenji
 ;; WAKAMIYA) and handa@etl.go.jp (Kenichi Handa).
 
-(defun mime-body-charset-chooser-for-mule (begin end)
-  "Return a cons of charset and encoding of a message in a given
-region.  Encoding name must be a canonical name, such as `base64'.
-US-ASCII, ISO-8859-* (except for ISO-8859-6), ISO-2022-JP,
-ISO-2022-JP-2 and ISO-2022-INT-1 are supported on Mule.  Either of
-charset ISO-2022-JP-2 or ISO-2022-INT-1 is used for multilingual text
-in Mule."
-  (let ((lclist (find-charset-region begin end)))
-    (cond ((null lclist)
-          '("US-ASCII" . nil))         ;Default charset of MIME.
-         ;; Multilingual capability requred.
-         ((and (> (length lclist) 1)
-               (boundp '*iso-2022-int-1*))
-          '("ISO-2022-INT-1" . nil))
-         ((> (length lclist) 1)
-          '("ISO-2022-JP-2" . nil))
-         ;; Simple charset.
-         ((memq lc-ltn1 lclist)
-          '("ISO-8859-1" . "quoted-printable"))
-         ((memq lc-ltn2 lclist)
-          '("ISO-8859-2" . "quoted-printable"))
-         ((memq lc-ltn3 lclist)
-          '("ISO-8859-3" . "quoted-printable"))
-         ((memq lc-ltn4 lclist)
-          '("ISO-8859-4" . "quoted-printable"))
-         ((memq lc-crl lclist)
-          '("ISO-8859-5" . "quoted-printable"))
-         ;;((memq lc-arb lclist)
-         ;; '("ISO-8859-6" . "quoted-printable"))
-         ((memq lc-grk lclist)
-          '("ISO-8859-7" . "quoted-printable"))
-         ((memq lc-hbw lclist)
-          '("ISO-8859-8" . "quoted-printable"))
-         ((memq lc-ltn5 lclist)
-          '("ISO-8859-9" . "quoted-printable"))
-         ((memq lc-jp lclist)
-          '("ISO-2022-JP" . nil))
-         ;; Unknown charset.
-         ((boundp '*iso-2022-int-1*)
-          '("ISO-2022-INT-1" . nil))
-         (t
-          '("ISO-2022-JP-2" . nil))
-         )))
-
 (defun mime-string-encoder-for-mule (method string)
   "For given METHOD that is a cons of charset and encoding, encode a
 STRING.  US-ASCII, ISO-8859-* (except for ISO-8859-6), ISO-2022-JP,
@@ -1633,6 +2059,7 @@ text."
                        ("ISO-8859-9" . *iso-8859-9*)
                        ("ISO-2022-JP" . *junet*)
                        ("ISO-2022-JP-2" . *iso-2022-ss2-7*)
+                       ("ISO-2022-KR" . *korean-mail*)
                        ("ISO-2022-INT-1" . *iso-2022-int-1*)
                        )))))
     ;; In bilingual environment it may be unnecessary to convert the
@@ -1724,12 +2151,14 @@ a recording host instead of local host."
       (let ((header-start (point))
            (case-fold-search t)
            beg end)
+       ;; for Emacs 18
+       ;; (if (re-search-forward "^$" (marker-position (mark-marker)))
        (if (re-search-forward "^$" (mark t))
            (narrow-to-region header-start (match-beginning 0))
          )
        (goto-char header-start)
        (while (and (re-search-forward
-                    mime-editor/yank-ignored-fields-regexp nil t)
+                    mime-editor/yank-ignored-field-regexp nil t)
                    (setq beg (match-beginning 0))
                    (setq end (1+ (rfc822/field-end)))
                    )
@@ -1737,132 +2166,6 @@ a recording host instead of local host."
          )
        ))))
 
-;;; mime.el ends here
-
-(defun mime-editor/translate-region (beg end &optional boundary multipart)
-  (if (null boundary)
-      (setq boundary
-           (concat mime-multipart-boundary " " (current-time-string)))
-    )
-  (save-excursion
-    (save-restriction
-      (narrow-to-region beg end)
-      (let ((tag nil)                  ;MIME tag
-           (contype nil)               ;Content-Type
-           (encoding nil)              ;Content-Transfer-Encoding
-           (nparts 0))                 ;Number of body parts
-       ;; Normalize the body part by inserting appropriate message
-       ;; tags for every message contents.
-       (mime-editor/normalize-body)
-       ;; Counting the number of Content-Type.
-       (goto-char (point-min))
-       (while (re-search-forward mime-editor/single-part-tag-regexp nil t)
-         (setq nparts (1+ nparts)))
-       ;; Begin translation.
-       (cond ((and (<= nparts 1)(not multipart))
-              ;; It's a singular message.
-              (goto-char (point-min))
-              (while (re-search-forward
-                      mime-editor/single-part-tag-regexp nil t)
-                (setq tag
-                      (buffer-substring (match-beginning 0) (match-end 0)))
-                (delete-region (match-beginning 0) (1+ (match-end 0)))
-                (setq contype (mime-editor/get-contype tag))
-                (setq encoding (mime-editor/get-encoding tag))
-                ))
-             (t
-              ;; It's a multipart message.
-              (goto-char (point-min))
-              (while (re-search-forward
-                      mime-editor/single-part-tag-regexp nil t)
-                (setq tag
-                      (buffer-substring (match-beginning 0) (match-end 0)))
-                (delete-region (match-beginning 0) (match-end 0))
-                (setq contype (mime-editor/get-contype tag))
-                (setq encoding (mime-editor/get-encoding tag))
-                (insert "--" boundary "\n")
-                (insert "Content-Type: " contype "\n")
-                (if encoding
-                    (insert "Content-Transfer-Encoding: " encoding "\n"))
-                )
-              ;; Define Content-Type as "multipart/mixed".
-              (setq contype
-                    (concat "multipart/mixed; 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))
-              (if (not (= (preceding-char) ?\n))
-                  ;; Boundary must start with a newline.
-                  (insert "\n"))
-              (insert "--" boundary "--\n")))
-       (list contype encoding boundary nparts)
-       ))))
-
-
-(defun mime-editor/find-inmost ()
-  (goto-char (point-min))
-  (if (re-search-forward mime-editor/multipart-beginning-regexp nil t)
-      (let ((bb (match-beginning 0))
-           (be (match-end 0))
-           (type (buffer-substring (match-beginning 1)(match-end 1)))
-           end-exp eb ee)
-       (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 (point-max))
-         (setq ee (point-max))
-         )
-       (narrow-to-region be eb)
-       (goto-char be)
-       (if (re-search-forward mime-editor/multipart-beginning-regexp nil t)
-           (let (ret)
-             (narrow-to-region (match-beginning 0)(point-max))
-             (mime-editor/find-inmost)
-             )
-         (widen)
-         ;;(delete-region eb ee)
-         (list type bb be eb)
-         ))))
-
-(defun mime-editor/process-multipart-1 (boundary)
-  (let ((ret (mime-editor/find-inmost)))
-    (if ret
-       (let ((type (car ret))
-             (bb (nth 1 ret))(be (nth 2 ret))
-             (eb (nth 3 ret))
-             )
-         (narrow-to-region bb eb)
-         (delete-region bb be)
-         (setq bb (point-min))
-         (setq eb (point-max))
-         (widen)
-         (goto-char eb)
-         (if (looking-at mime-editor/multipart-end-regexp)
-             (let ((beg (match-beginning 0))
-                   (end (match-end 0))
-                   )
-               (delete-region beg end)
-               (if (and (not (looking-at mime-editor/single-part-tag-regexp))
-                        (not (eobp)))
-                   (insert (concat (mime-make-text-tag) "\n"))
-                 )))
-         (setq boundary
-               (nth 2 (mime-editor/translate-region bb eb
-                                                    boundary t)))
-         (goto-char bb)
-         (insert
-          (format "--[[multipart/%s; boundary=\"%s\"][7bit]]\n"
-                  type boundary))
-         boundary))))
-
 
 ;;; @ multipart enclosure
 ;;;
@@ -1870,37 +2173,28 @@ a recording host instead of local host."
 (defun mime-editor/enclose-region (type beg end)
   (save-excursion
     (goto-char beg)
-    (let ((f (bolp)))
+    (let ((current (point))
+         exist-prev-tag)
+      (save-excursion
+       (if (mime-editor/goto-tag)
+           (or (eq current (match-beginning 0))
+               (setq exist-prev-tag t)
+               )))
       (save-restriction
        (narrow-to-region beg end)
        (goto-char beg)
-       (if (not f)
+        (if exist-prev-tag
            (insert "\n")
          )
        (insert (format "--<<%s>>-{\n" type))
        (goto-char (point-max))
-       (setq f (bolp))
-       (if (not f)
-           (insert (format "\n--}-<<%s>>" type))
-         (insert (format "--}-<<%s>>\n" type))
-         )
+       (insert (format "\n--}-<<%s>>\n" type))
        (goto-char (point-max))
        )
-      (if (not (eobp))
-         (progn
-           (if (not f)
-               (if (not (eolp))
-                   (insert "\n")
-                 (forward-char)
-                 )
-             )
-           (if (not (looking-at mime-editor/single-part-tag-regexp))
-               (insert (mime-make-text-tag) "\n")
-             )
-           )
-       (if (not f)
-           (insert "\n")
-         ))
+      (if (and (not (looking-at mime-editor/single-part-tag-regexp))
+              (not (eobp)))
+         (insert (mime-make-text-tag) "\n")
+       )
       )))
 
 (defun mime-editor/enclose-mixed-region (beg end)
@@ -1923,6 +2217,109 @@ a recording host instead of local host."
   (mime-editor/enclose-region "alternative" beg end)
   )
 
+(defun mime-editor/enclose-signed-region (beg end)
+  (interactive "*r")
+  (if mime-editor/signing-type
+      (mime-editor/enclose-region "signed" beg end)
+    (message "Please specify signing type.")
+    ))
+
+(defun mime-editor/enclose-encrypted-region (beg end)
+  (interactive "*r")
+  (if mime-editor/signing-type
+      (mime-editor/enclose-region "encrypted" beg end)
+    (message "Please specify encrypting type.")
+    ))
+
+(defun mime-editor/insert-key (&optional arg)
+  "Insert a pgp public key."
+  (interactive "P")
+  (mime-editor/insert-tag "application" "pgp-keys")
+  (mime-editor/define-encoding "7bit")
+  (mc-insert-public-key)
+  )
+
+
+;;; @ flag setting
+;;;
+
+(defun mime-editor/set-split (arg)
+  (interactive
+   (list
+    (y-or-n-p "Do you want to enable split?")
+    ))
+  (setq mime-editor/split-message arg)
+  (if arg
+      (message "This message is enabled to split.")
+    (message "This message is not enabled to split.")
+    ))
+
+
+;;; @ pgp
+;;;
+
+(defun mime-editor/set-sign (arg)
+  (interactive
+   (list
+    (y-or-n-p "Do you want to sign?")
+    ))
+  (if arg
+      (progn
+       (setq mime-editor/pgp-processing 'sign)
+       (message "This message will be signed.")
+       )
+    (if (eq mime-editor/pgp-processing 'sign)
+       (setq mime-editor/pgp-processing nil)
+      )
+    (message "This message will not be signed.")
+    ))
+
+(defun mime-editor/set-encrypt (arg)
+  (interactive
+   (list
+    (y-or-n-p "Do you want to encrypt?")
+    ))
+  (if arg
+      (progn
+       (setq mime-editor/pgp-processing 'encrypt)
+       (message "This message will be encrypt.")
+       )
+    (if (eq mime-editor/pgp-processing 'encrypt)
+       (setq mime-editor/pgp-processing nil)
+      )
+    (message "This message will not be encrypt.")
+    ))
+
+(defvar mime-editor/pgp-processing nil)
+(make-variable-buffer-local 'mime-editor/pgp-processing)
+
+(defun mime-editor/call-mc (command)
+  (let* ((header (rfc822/get-header-string-except
+                 "^Content-Type:" mail-header-separator)))
+    (goto-char (point-min))
+    (if (search-forward mail-header-separator)
+       (replace-match "")
+      )
+    (goto-char (point-min))
+    (insert header)
+    (insert "Content-Type: application/pgp; format=mime\n")
+    (insert mail-header-separator)
+    (insert "\n")
+    (if (null (call-interactively command))
+       (throw 'mime-editor/error 'pgp-error)
+      )
+    ))
+
+(defun mime-editor/pgp-processing ()
+  (let ((command
+        (cdr (assq mime-editor/pgp-processing
+                   '((sign    . mc-sign)
+                     (encrypt . mc-encrypt)
+                     )))))
+    (and command
+        (mime-editor/call-mc command)
+        )))
+
 
 ;;; @ split
 ;;;
@@ -1938,8 +2335,142 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
                  id number total separator))
   )
 
-(defun mime-editor/split-and-send (&optional cmd)
+(defun mime-editor/split-and-send
+  (&optional cmd lines mime-editor/message-max-length)
+  (interactive)
+  (or lines
+      (setq lines
+           (count-lines (point-min) (point-max)))
+      )
+  (or mime-editor/message-max-length
+      (setq mime-editor/message-max-length
+           (or (cdr (assq major-mode mime-editor/message-max-length-alist))
+               mime-editor/message-default-max-length))
+      )
+  (let* ((mime-editor/draft-file-name 
+         (or (buffer-file-name)
+             (make-temp-name
+              (expand-file-name "tm-draft" mime/tmp-dir))))
+        (separator mail-header-separator)
+        (config
+         (eval (cdr (assq major-mode mime-editor/window-config-alist))))
+        (id (concat "\""
+                    (replace-space-with-underline (current-time-string))
+                    "@" (system-name) "\"")))
+    (run-hooks 'mime-editor/before-split-hook)
+    (let* ((header (rfc822/get-header-string-except
+                   mime-editor/split-ignored-field-regexp separator))
+          (subject (mail-fetch-field "subject"))
+          (total (+ (/ lines mime-editor/message-max-length)
+                    (if (> (mod lines mime-editor/message-max-length) 0)
+                        1)))
+          (the-buf (current-buffer))
+          (buf (get-buffer "*tmp-send*"))
+          (command
+           (or cmd
+               (cdr
+                (assq major-mode
+                      mime-editor/split-message-sender-alist))
+               (cdr
+                (assq major-mode
+                      mime-editor/message-default-sender-alist))
+               ))
+          data)
+      (goto-char (point-min))
+      (if (re-search-forward (concat "^" (regexp-quote separator) "$")
+                            nil t)
+         (replace-match "")
+       )
+      (if buf
+         (progn
+           (switch-to-buffer buf)
+           (erase-buffer)
+           (switch-to-buffer the-buf)
+           )
+       (setq buf (get-buffer-create "*tmp-send*"))
+       )
+      (switch-to-buffer buf)
+      (make-local-variable 'mail-header-separator)
+      (setq mail-header-separator separator)
+      (switch-to-buffer the-buf)
+      (goto-char (point-min))
+      (re-search-forward "^$" nil t)
+      (let ((mime-editor/partial-number 1))
+       (setq data (buffer-substring
+                   (point-min)
+                   (progn
+                     (goto-line mime-editor/message-max-length)
+                     (point))
+                   ))
+       (delete-region (point-min)(point))
+       (switch-to-buffer buf)
+       (mime-editor/insert-partial-header
+        header subject id mime-editor/partial-number total separator)
+       (insert data)
+       (save-excursion
+         (save-restriction
+           (goto-char (point-min))
+           (search-forward (concat "\n" mail-header-separator "\n"))
+           (narrow-to-region
+            (match-end 0)
+            (if (re-search-forward "^$" nil t)
+                (match-beginning 0)
+              (point-max)
+              ))
+           (goto-char (point-min))
+           (while (re-search-forward
+                   mime-editor/split-blind-field-regexp nil t)
+             (delete-region (match-beginning 0)
+                            (let ((e (rfc822/field-end)))
+                              (if (< e (point-max))
+                                  (1+ e)
+                                e)))
+             )
+           ))
+       (save-excursion
+         (message (format "Sending %d/%d..."
+                          mime-editor/partial-number total))
+         (call-interactively command)
+         (message (format "Sending %d/%d... done"
+                          mime-editor/partial-number total))
+         )
+       (erase-buffer)
+       (switch-to-buffer the-buf)
+       (setq mime-editor/partial-number 2)
+       (while (< mime-editor/partial-number total)
+         (setq data (buffer-substring
+                     (point-min)
+                     (progn
+                       (goto-line mime-editor/message-max-length)
+                       (point))
+                     ))
+         (delete-region (point-min)(point))
+         (switch-to-buffer buf)
+         (mime-editor/insert-partial-header
+          header subject id mime-editor/partial-number total separator)
+         (insert data)
+         (save-excursion
+           (message (format "Sending %d/%d..."
+                            mime-editor/partial-number total))
+           (call-interactively command)
+           (message (format "Sending %d/%d... done"
+                            mime-editor/partial-number total))
+           )
+         (erase-buffer)
+         (switch-to-buffer the-buf)
+         (setq mime-editor/partial-number
+               (1+ mime-editor/partial-number))
+         )
+       (goto-char (point-min))
+       (mime-editor/insert-partial-header
+        header subject id mime-editor/partial-number total separator)
+       (message (format "Sending %d/%d..."
+                        mime-editor/partial-number total))
+       ))))
+
+(defun mime-editor/maybe-split-and-send (&optional cmd)
   (interactive)
+  (run-hooks 'mime-editor/before-send-hook)
   (let ((mime-editor/message-max-length
         (or (cdr (assq major-mode mime-editor/message-max-length-alist))
             mime-editor/message-default-max-length))
@@ -1947,126 +2478,8 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
        )
     (if (and (> lines mime-editor/message-max-length)
             mime-editor/split-message)
-       (let* ((mime-editor/draft-file-name 
-               (or (buffer-file-name)
-                   (make-temp-name
-                    (expand-file-name "tm-draft" mime/tmp-dir))))
-              (separator mail-header-separator)
-              (config
-               (eval (cdr (assq major-mode mime-editor/window-config-alist))))
-              (id (concat "\""
-                          (replace-space-with-underline (current-time-string))
-                          "@" (system-name) "\"")))
-         (run-hooks 'mime-editor/before-split-hook)
-         (let* ((header (rfc822/get-header-string-except
-                         mime-editor/split-ignored-fields-regexp separator))
-                (subject (mail-fetch-field "subject"))
-                (total (+ (/ lines mime-editor/message-max-length)
-                          (if (> (mod lines mime-editor/message-max-length) 0)
-                              1)))
-                (the-buf (current-buffer))
-                (buf (get-buffer "*tmp-send*"))
-                (command
-                 (or cmd
-                     (cdr
-                      (assq major-mode
-                            mime-editor/split-message-sender-alist))
-                     (cdr
-                      (assq major-mode
-                            mime-editor/message-default-sender-alist))
-                     ))
-                data)
-           (goto-char (point-min))
-           (if (re-search-forward (concat "^" (regexp-quote separator) "$")
-                                  nil t)
-               (replace-match "")
-             )
-           (if buf
-               (progn
-                 (switch-to-buffer buf)
-                 (erase-buffer)
-                 (switch-to-buffer the-buf)
-                 )
-             (setq buf (get-buffer-create "*tmp-send*"))
-             )
-           (switch-to-buffer buf)
-           (make-variable-buffer-local 'mail-header-separator)
-           (setq mail-header-separator separator)
-           (switch-to-buffer the-buf)
-           (goto-char (point-min))
-           (re-search-forward "^$" nil t)
-           (let ((mime-editor/partial-number 1))
-             (setq data (buffer-substring
-                         (point-min)
-                         (progn
-                           (goto-line mime-editor/message-max-length)
-                           (point))
-                         ))
-             (delete-region (point-min)(point))
-             (switch-to-buffer buf)
-             (mime-editor/insert-partial-header
-              header subject id mime-editor/partial-number total separator)
-             (insert data)
-             (save-excursion
-               (save-restriction
-                 (goto-char (point-min))
-                 (search-forward (concat "\n" mail-header-separator "\n"))
-                 (narrow-to-region
-                  (match-end 0)
-                  (if (re-search-forward "^$" nil t)
-                      (match-beginning 0)
-                    (point-max)
-                    ))
-                 (goto-char (point-min))
-                 (while (re-search-forward
-                         mime-editor/split-blind-fields-regexp nil t)
-                   (delete-region (match-beginning 0)
-                                  (let ((e (rfc822/field-end)))
-                                    (if (< e (point-max))
-                                        (1+ e)
-                                      e)))
-                   )
-                 ))
-             (save-excursion
-               (message (format "Sending %d/%d..."
-                                mime-editor/partial-number total))
-               (call-interactively command)
-               (message (format "Sending %d/%d... done"
-                                mime-editor/partial-number total))
-               )
-             (erase-buffer)
-             (switch-to-buffer the-buf)
-             (setq mime-editor/partial-number 2)
-             (while (< mime-editor/partial-number total)
-               (setq data (buffer-substring
-                           (point-min)
-                           (progn
-                             (goto-line mime-editor/message-max-length)
-                             (point))
-                           ))
-               (delete-region (point-min)(point))
-               (switch-to-buffer buf)
-               (mime-editor/insert-partial-header
-                header subject id mime-editor/partial-number total separator)
-               (insert data)
-               (save-excursion
-                 (message (format "Sending %d/%d..."
-                                  mime-editor/partial-number total))
-                 (call-interactively command)
-                 (message (format "Sending %d/%d... done"
-                                  mime-editor/partial-number total))
-                 )
-               (erase-buffer)
-               (switch-to-buffer the-buf)
-               (setq mime-editor/partial-number
-                     (1+ mime-editor/partial-number))
-               )
-             (goto-char (point-min))
-             (mime-editor/insert-partial-header
-              header subject id mime-editor/partial-number total separator)
-             (message (format "Sending %d/%d..."
-                              mime-editor/partial-number total))
-             ))))))
+       (mime-editor/split-and-send cmd lines mime-editor/message-max-length)
+      )))
 
 
 ;;; @ preview message
@@ -2137,7 +2550,7 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
 
 (defun mime-editor/draft-preview ()
   (interactive)
-  (let ((sep (assoc-value major-mode mime-editor/draft-header-separator-alist)))
+  (let ((sep (cdr (assq major-mode mime-editor/draft-header-separator-alist))))
     (or (stringp sep) (setq sep (eval sep)))
     (make-variable-buffer-local 'mime::article/draft-header-separator)
     (goto-char (point-min))
@@ -2151,7 +2564,7 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
     ))
 
 (defun mime-viewer::quitting-method/draft-preview ()
-  (let ((mother mime/mother-buffer))
+  (let ((mother mime::preview/mother-buffer))
     (save-excursion
       (switch-to-buffer mother)
       (goto-char (point-min))
@@ -2199,3 +2612,5 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
 (provide 'tm-edit)
 
 (run-hooks 'tm-edit-load-hook)
+
+;;; tm-edit.el ends here