tm 7.81.
[elisp/tm.git] / tm-ew-e.el
index 0150f19..a08771e 100644 (file)
@@ -1,21 +1,68 @@
-;;;
-;;; tm-ew-d.el --- RFC 1522 based multilingual MIME message header
-;;;                encoder for GNU Emacs
-;;;
-;;; Copyright (C) 1995 Free Software Foundation, Inc.
-;;; Copyright (C) 1993,1994,1995 MORIOKA Tomohiko
-;;;
-;;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
-;;; Version:
-;;;    $Id: tm-ew-e.el,v 7.0 1995/10/03 04:35:11 morioka Exp $
-;;; Keywords: mail, news, MIME, RFC 1522, multilingual, encoded-word
-;;;
+;;; tm-ew-e.el --- RFC 1522 based MIME encoded-word encoder for GNU Emacs
+
+;; Copyright (C) 1995,1996 Free Software Foundation, Inc.
+
+;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; Version: $Revision: 7.47 $
+;; Keywords: mail, news, MIME, RFC 1522, multilingual, encoded-word
+
+;; 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; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Code:
 
 (require 'mel)
 
 (require 'mel)
-(require 'tl-822)
+(require 'std11)
 (require 'tm-def)
 
 
 (require 'tm-def)
 
 
+;;; @ version
+;;;
+
+(defconst tm-ew-e/RCS-ID
+  "$Id: tm-ew-e.el,v 7.47 1996/08/30 04:26:46 morioka Exp $")
+(defconst mime-eword/encoder-version (get-version-string tm-ew-e/RCS-ID))
+
+
+;;; @ variables
+;;;
+
+(defvar mime/no-encoding-header-fields '("X-Nsubject" "Newsgroups"))
+
+(defvar mime/use-X-Nsubject nil)
+
+(defvar mime-eword/charset-encoding-alist
+  '((us-ascii          . nil)
+    (iso-8859-1                . "Q")
+    (iso-8859-2                . "Q")
+    (iso-8859-3                . "Q")
+    (iso-8859-4                . "Q")
+    (iso-8859-5                . "Q")
+    (koi8-r            . "Q")
+    (iso-8859-7                . "Q")
+    (iso-8859-8                . "Q")
+    (iso-8859-9                . "Q")
+    (iso-2022-jp       . "B")
+    (iso-2022-kr       . "B")
+    (euc-kr            . "B")
+    (iso-2022-jp-2     . "B")
+    (iso-2022-int-1    . "B")
+    ))
+
 ;;; @ encoded-text encoder
 ;;;
 
 ;;; @ encoded-text encoder
 ;;;
 
@@ -28,7 +75,8 @@
               )
         ))
     (if text
               )
         ))
     (if text
-       (concat "=?" charset "?" encoding "?" text "?=")
+       (concat "=?" (upcase (symbol-name charset)) "?"
+               encoding "?" text "?=")
       )))
 
 
       )))
 
 
     ))
 
 (defun tm-eword::parse-lc-word (str)
     ))
 
 (defun tm-eword::parse-lc-word (str)
-  (let* ((rest (string-to-char-list str))
-        (chr (car rest))
+  (let* ((chr (sref str 0))
         (lc (tm-eword::char-type chr))
         (lc (tm-eword::char-type chr))
-        (p (char-bytes chr))
+        (i (char-length chr))
+        (len (length str))
         )
         )
-    (catch 'tag
-      (while (setq rest (cdr rest))
-       (setq chr (car rest))
-       (if (not (eq lc (tm-eword::char-type chr)))
-           (throw 'tag nil)
-         )
-       (setq p (+ p (char-bytes chr)))
-       ))
-    (cons (cons lc (substring str 0 p)) (substring str p))
+    (while (and (< i len)
+               (setq chr (sref str i))
+               (eq lc (tm-eword::char-type chr))
+               )
+      (setq i (+ i (char-length chr)))
+      )
+    (cons (cons lc (substring str 0 i)) (substring str i))
     ))
 
 (defun tm-eword::split-to-lc-words (str)
     ))
 
 (defun tm-eword::split-to-lc-words (str)
 ;;; @ rule
 ;;;
 
 ;;; @ rule
 ;;;
 
-(defun mime/find-charset-rule (lcl)
-  (if lcl
-      (let ((ret (some-element
-                 (function
-                  (lambda (elt)
-                    (subsetp lcl (car elt))
-                    ))
-                 mime/lc-charset-rule-list)
-                ))
-       (if ret
-           (cdr ret)
-         mime/unknown-charset-rule)
-       )
-    '(nil nil)
-    ))
+(defmacro tm-eword::make-rword (text charset encoding type)
+  (` (list (, text)(, charset)(, encoding)(, type))))
+(defmacro tm-eword::rword-text (rword)
+  (` (car (, rword))))
+(defmacro tm-eword::rword-charset (rword)
+  (` (car (cdr (, rword)))))
+(defmacro tm-eword::rword-encoding (rword)
+  (` (car (cdr (cdr (, rword))))))
+(defmacro tm-eword::rword-type (rword)
+  (` (car (cdr (cdr (cdr (, rword)))))))
+
+(defun tm-eword::find-charset-rule (charsets)
+  (if charsets
+      (let* ((charset (charsets-to-mime-charset charsets))
+            (encoding (cdr (assq charset mime-eword/charset-encoding-alist)))
+            )
+       (list charset encoding)
+       )))
 
 
-(defun tm-eword::words-to-ruled-words (wl)
+(defun tm-eword::words-to-ruled-words (wl &optional mode)
   (mapcar (function
           (lambda (word)
   (mapcar (function
           (lambda (word)
-            (cons (cdr word) (mime/find-charset-rule (car word)))
-            ))
+            (let ((ret (tm-eword::find-charset-rule (car word))))
+              (tm-eword::make-rword (cdr word) (car ret)(nth 1 ret) mode)
+              )))
          wl))
 
 (defun tm-eword::space-process (seq)
          wl))
 
 (defun tm-eword::space-process (seq)
       (setq b (car seq))
       (setq seq (cdr seq))
       (setq c (car seq))
       (setq b (car seq))
       (setq seq (cdr seq))
       (setq c (car seq))
-      (setq cc (nth 1 c))
-      (if (null (nth 1 b))
+      (setq cc (tm-eword::rword-charset c))
+      (if (null (tm-eword::rword-charset b))
          (progn
            (setq a (car prev))
          (progn
            (setq a (car prev))
-           (setq ac (nth 1 a))
-           (if (and (nth 2 a)(nth 2 c))
-               (cond ((equal ac cc)
+           (setq ac (tm-eword::rword-charset a))
+           (if (and (tm-eword::rword-encoding a)
+                    (tm-eword::rword-encoding c))
+               (cond ((eq ac cc)
                       (setq prev (cons
                                   (cons (concat (car a)(car b)(car c))
                                         (cdr a))
                       (setq prev (cons
                                   (cons (concat (car a)(car b)(car c))
                                         (cdr a))
     (reverse prev)
     ))
 
     (reverse prev)
     ))
 
-(defun tm-eword::split-string (str)
+(defun tm-eword::split-string (str &optional mode)
   (tm-eword::space-process
   (tm-eword::space-process
-   (tm-eword::words-to-ruled-words
-    (tm-eword::lc-words-to-words
-     (tm-eword::split-to-lc-words str)
-     ))))
+   (tm-eword::words-to-ruled-words (tm-eword::lc-words-to-words
+                                   (tm-eword::split-to-lc-words str))
+                                  mode)))
 
 
 ;;; @ length
 ;;;
 
 
 
 ;;; @ length
 ;;;
 
-(defun base64-length (string)
-  (let ((l (length string)))
-    (* (+ (/ l 3)
-         (if (= (mod l 3) 0) 0 1)
-         ) 4)
-    ))
-
-(defun q-encoding-length (string)
-  (let ((l 0)(i 0)(len (length string)) chr)
-    (while (< i len)
-      (setq chr (elt string i))
-      (if (string-match "[A-Za-z0-9!*+/=_---]" (char-to-string chr))
-         (setq l (+ l 1))
-       (setq l (+ l 3))
-       )
-      (setq i (+ i 1)) )
-    l))
-
 (defun tm-eword::encoded-word-length (rword)
 (defun tm-eword::encoded-word-length (rword)
-  (let ((charset  (nth 1 rword))
-       (encoding (nth 2 rword))
-       (string   (car rword))
+  (let ((string   (tm-eword::rword-text     rword))
+       (charset  (tm-eword::rword-charset  rword))
+       (encoding (tm-eword::rword-encoding rword))
        ret)
     (setq ret
        ret)
     (setq ret
-         (cond ((equal encoding "B")
-                (setq string
-                      (mime/convert-string-from-emacs string charset))
-                (base64-length string)
+         (cond ((string-equal encoding "B")
+                (setq string (encode-mime-charset-string string charset))
+                (base64-encoded-length string)
                 )
                 )
-               ((equal encoding "Q")
-                (setq string
-                      (mime/convert-string-from-emacs string charset))
-                (q-encoding-length string)
+               ((string-equal encoding "Q")
+                (setq string (encode-mime-charset-string string charset))
+                (q-encoding-encoded-length string
+                                           (tm-eword::rword-type rword))
                 )))
     (if ret
                 )))
     (if ret
-       (cons (+ 7 (length charset) ret) string)
+       (cons (+ 7 (length (symbol-name charset)) ret) string)
       )))
 
 
 ;;; @ encode-string
 ;;;
 
       )))
 
 
 ;;; @ encode-string
 ;;;
 
-(defun tm-eword::encode-string-1 (column rwl &optional mode)
+(defun tm-eword::encode-string-1 (column rwl)
   (let* ((rword (car rwl))
         (ret (tm-eword::encoded-word-length rword))
         string len)
   (let* ((rword (car rwl))
         (ret (tm-eword::encoded-word-length rword))
         string len)
                  )
             (setq string
                   (tm-eword::encode-encoded-text
                  )
             (setq string
                   (tm-eword::encode-encoded-text
-                   (nth 1 rword) (nth 2 rword) (cdr ret)
+                   (tm-eword::rword-charset rword)
+                   (tm-eword::rword-encoding rword)
+                   (cdr ret)
+                   (tm-eword::rword-type rword)
                    ))
             (setq len (+ (length string) column))
             (setq rwl (cdr rwl))
             )
            (t
             (setq string (car rword))
                    ))
             (setq len (+ (length string) column))
             (setq rwl (cdr rwl))
             )
            (t
             (setq string (car rword))
-            (let* ((ls (reverse (string-to-char-list string)))
-                   (sl (length string))
-                   (p sl) str)
-              (while (and ls
+            (let* ((sl (length string))
+                   (p 0) np
+                   (str "") nstr)
+              (while (and (< p len)
                           (progn
                           (progn
-                            (setq p (- p (char-bytes (car ls))))
-                            (setq str (substring string 0 p))
+                            (setq np (+ p (char-length (sref string p))))
+                            (setq nstr (substring string 0 np))
                             (setq ret (tm-eword::encoded-word-length
                             (setq ret (tm-eword::encoded-word-length
-                                       (cons str (cdr rword))
+                                       (cons nstr (cdr rword))
                                        ))
                                        ))
-                            (setq str (cdr ret))
+                            (setq nstr (cdr ret))
                             (setq len (+ (car ret) column))
                             (setq len (+ (car ret) column))
-                            (> len 76)
+                            (<= len 76)
                             ))
                             ))
-                (setq ls (cdr ls))
-                )
-              (if ls
-                  (progn
-                    (setq rwl (cons (cons (substring string p) (cdr rword))
-                                    (cdr rwl)))
-                    (setq string
-                          (tm-eword::encode-encoded-text
-                           (nth 1 rword) (nth 2 rword) str))
-                    (setq len (+ (length string) column))
-                    )
-                (setq string "\n ")
-                (setq len 1)
+                (setq str nstr
+                      p np))
+              (if (string-equal str "")
+                  (setq string "\n "
+                        len 1)
+                (setq rwl (cons (cons (substring string p) (cdr rword))
+                                (cdr rwl)))
+                (setq string
+                      (tm-eword::encode-encoded-text
+                       (tm-eword::rword-charset rword)
+                       (tm-eword::rword-encoding rword)
+                       str
+                       (tm-eword::rword-type rword)))
+                (setq len (+ (length string) column))
                 )
               )))
       )
     (list string len rwl)
     ))
 
                 )
               )))
       )
     (list string len rwl)
     ))
 
-(defun tm-eword::encode-rwl (column rwl &optional mode)
-  (let (ret dest)
+(defun tm-eword::encode-rwl (column rwl)
+  (let (ret dest ps special str ew-f pew-f)
     (while rwl
     (while rwl
-      (setq ret (tm-eword::encode-string-1 column rwl mode))
-      (setq dest (concat dest (car ret))
-           column (nth 1 ret)
+      (setq ew-f (nth 2 (car rwl)))
+      (if (and pew-f ew-f)
+         (setq rwl (cons '(" ") rwl)
+               pew-f nil)
+       (setq pew-f ew-f)
+       )
+      (setq ret (tm-eword::encode-string-1 column rwl))
+      (setq str (car ret))
+      (if (eq (elt str 0) ?\n)
+         (if (eq special ?\()
+             (progn
+               (setq dest (concat dest "\n ("))
+               (setq ret (tm-eword::encode-string-1 2 rwl))
+               (setq str (car ret))
+               ))
+       (cond ((eq special 32)
+              (if (string= str "(")
+                  (setq ps t)
+                (setq dest (concat dest " "))
+                (setq ps nil)
+                ))
+             ((eq special ?\()
+              (if ps
+                  (progn
+                    (setq dest (concat dest " ("))
+                    (setq ps nil)
+                    )
+                (setq dest (concat dest "("))
+                )
+              )))
+      (cond ((string= str " ")
+            (setq special 32)
+            )
+           ((string= str "(")
+            (setq special ?\()
+            )
+           (t
+            (setq special nil)
+            (setq dest (concat dest str))
+            ))
+      (setq column (nth 1 ret)
            rwl (nth 2 ret))
       )
     (list dest column)
     ))
 
 (defun tm-eword::encode-string (column str &optional mode)
            rwl (nth 2 ret))
       )
     (list dest column)
     ))
 
 (defun tm-eword::encode-string (column str &optional mode)
-  (tm-eword::encode-rwl column (tm-eword::split-string str) mode)
+  (tm-eword::encode-rwl column (tm-eword::split-string str mode))
   )
 
 
   )
 
 
 ;;;
 
 (defun tm-eword::phrase-to-rwl (phrase)
 ;;;
 
 (defun tm-eword::phrase-to-rwl (phrase)
-  (let (token type dest)
+  (let (token type dest str)
     (while phrase
       (setq token (car phrase))
       (setq type (car token))
       (cond ((eq type 'quoted-string)
     (while phrase
       (setq token (car phrase))
       (setq type (car token))
       (cond ((eq type 'quoted-string)
+            (setq str (concat "\"" (cdr token) "\""))
             (setq dest
                   (append dest
             (setq dest
                   (append dest
-                          '(("\"" nil nil))
-                          (tm-eword::words-to-ruled-words
-                           (tm-eword::lc-words-to-words
-                            (tm-eword::split-to-lc-words (cdr token))))
-                          '(("\"" nil nil))
-                          ))
+                          (list
+                           (let ((ret (tm-eword::find-charset-rule
+                                       (find-charset-string str))))
+                             (tm-eword::make-rword
+                              str (car ret)(nth 1 ret) 'phrase)
+                             )
+                           )))
             )
            ((eq type 'comment)
             (setq dest
             )
            ((eq type 'comment)
             (setq dest
                           '(("(" nil nil))
                           (tm-eword::words-to-ruled-words
                            (tm-eword::lc-words-to-words
                           '(("(" nil nil))
                           (tm-eword::words-to-ruled-words
                            (tm-eword::lc-words-to-words
-                            (tm-eword::split-to-lc-words (cdr token))))
+                            (tm-eword::split-to-lc-words (cdr token)))
+                           'comment)
                           '((")" nil nil))
                           ))
             )
                           '((")" nil nil))
                           ))
             )
                                (tm-eword::words-to-ruled-words
                                 (tm-eword::lc-words-to-words
                                  (tm-eword::split-to-lc-words (cdr token))
                                (tm-eword::words-to-ruled-words
                                 (tm-eword::lc-words-to-words
                                  (tm-eword::split-to-lc-words (cdr token))
-                                 ))))
+                                 ) 'phrase)))
             ))
       (setq phrase (cdr phrase))
       )
             ))
       (setq phrase (cdr phrase))
       )
       (let ((phrase (nth 1 phrase-route-addr))
            (route (nth 2 phrase-route-addr))
            dest)
       (let ((phrase (nth 1 phrase-route-addr))
            (route (nth 2 phrase-route-addr))
            dest)
+       (if (eq (car (car phrase)) 'spaces)
+           (setq phrase (cdr phrase))
+         )
        (setq dest (tm-eword::phrase-to-rwl phrase))
        (if dest
            (setq dest (append dest '((" " nil nil))))
          )
        (append
         dest
        (setq dest (tm-eword::phrase-to-rwl phrase))
        (if dest
            (setq dest (append dest '((" " nil nil))))
          )
        (append
         dest
-        (list (list (concat "<" (rfc822/addr-to-string route) ">") nil nil))
+        (list (list (concat "<" (std11-addr-to-string route) ">") nil nil))
         ))))
 
 (defun tm-eword::addr-spec-to-rwl (addr-spec)
   (if (eq (car addr-spec) 'addr-spec)
         ))))
 
 (defun tm-eword::addr-spec-to-rwl (addr-spec)
   (if (eq (car addr-spec) 'addr-spec)
-      (list (list (rfc822/addr-to-string (cdr addr-spec)) nil nil))
+      (list (list (std11-addr-to-string (cdr addr-spec)) nil nil))
     ))
 
 (defun tm-eword::mailbox-to-rwl (mbox)
     ))
 
 (defun tm-eword::mailbox-to-rwl (mbox)
              (append dest
                      '((" " nil nil)
                        ("(" nil nil))
              (append dest
                      '((" " nil nil)
                        ("(" nil nil))
-                     (tm-eword::split-string comment)
+                     (tm-eword::split-string comment 'comment)
                      '((")" nil nil))
                      )))
     dest))
                      '((")" nil nil))
                      )))
     dest))
 (defun tm-eword::encode-address-list (column str)
   (tm-eword::encode-rwl
    column
 (defun tm-eword::encode-address-list (column str)
   (tm-eword::encode-rwl
    column
-   (tm-eword::addresses-to-rwl
-    (rfc822/parse-addresses
-     (rfc822/lexical-analyze str)))))
+   (tm-eword::addresses-to-rwl (std11-parse-addresses-string str))
+   ))
+
+
+;;; @ application interfaces
+;;;
+
+(defun mime/encode-field (str)
+  (setq str (std11-unfold-string str))
+  (let ((ret (string-match std11-field-head-regexp str)))
+    (or (if ret
+           (let ((field-name (substring str 0 (1- (match-end 0))))
+                 (field-body (eliminate-top-spaces
+                              (substring str (match-end 0))))
+                 fname)
+             (if (setq ret
+                       (cond ((string-equal field-body "") "")
+                             ((member (setq fname (downcase field-name))
+                                      '("reply-to" "from" "sender"
+                                        "resent-reply-to" "resent-from"
+                                        "resent-sender" "to" "resent-to"
+                                        "cc" "resent-cc"
+                                        "bcc" "resent-bcc" "dcc")
+                                      )
+                              (car (tm-eword::encode-address-list
+                                    (+ (length field-name) 2) field-body))
+                              )
+                             (t
+                              (catch 'tag
+                                (let ((r mime/no-encoding-header-fields)
+                                      fn)
+                                  (while r
+                                    (setq fn (car r))
+                                    (if (string-equal (downcase fn) fname)
+                                        (throw 'tag field-body)
+                                      )
+                                    (setq r (cdr r))
+                                    ))
+                                (car (tm-eword::encode-string
+                                      (+ (length field-name) 1)
+                                      field-body 'text))
+                                ))
+                             ))
+                 (concat field-name ": " ret)
+               )))
+       (car (tm-eword::encode-string 0 str))
+       )))
+
+(defun mime/exist-encoded-word-in-subject ()
+  (let ((str (std11-field-body "Subject")))
+    (if (and str (string-match mime/encoded-word-regexp str))
+       str)))
+
+(defun mime/encode-message-header ()
+  (interactive "*")
+  (save-excursion
+    (save-restriction
+      (std11-narrow-to-header mail-header-separator)
+      (goto-char (point-min))
+      (let (beg end field)
+       (while (re-search-forward std11-field-head-regexp nil t)
+         (setq beg (match-beginning 0))
+         (setq end (std11-field-end))
+         (if (and (find-charset-region beg end)
+                  (setq field
+                        (mime/encode-field
+                         (buffer-substring-no-properties beg end)
+                         ))
+                  )
+             (progn
+               (delete-region beg end)
+               (insert field)
+               ))
+         ))
+      (if mime/use-X-Nsubject
+         (let ((str (mime/exist-encoded-word-in-subject)))
+           (if str
+               (insert
+                (concat
+                 "\nX-Nsubject: "
+                 (mime-eword/decode-string (std11-unfold-string str))
+                 )))))
+      )))
+
+(defun mime-eword/encode-string (str &optional column mode)
+  (car (tm-eword::encode-rwl (or column 0) (tm-eword::split-string str mode)))
+  )
 
 
 ;;; @ end
 ;;;
 
 (provide 'tm-ew-e)
 
 
 ;;; @ end
 ;;;
 
 (provide 'tm-ew-e)
+
+;;; tm-ew-e.el ends here