Path: galaxy.trc.rwcp.or.jp!jaist-news!cs.titech!wnoc-tyo-news!scslwide!wsgw!headgw!ptggw!enami
From: enami@sys.ptg.sony.co.jp (enami tsugutomo)
Newsgroups: fj.mail,fj.editor.mule
Subject: mime-kit.el 1.68->1.74 patch (was Re: introduction of MIME
	tools and small MIME FAQ)
Message-ID: <ENAMI.93Nov15215545@kitt.sys.ptg.sony.co.jp>
Date: 15 Nov 93 12:55:45 GMT
References: <MORIOKA.93Nov15004847@is15e0s03.jaist.ac.jp>
Sender: news@ptg.sony.co.jp
Organization: Sony Corp.  Production Technology Development Grp.
Lines: 377
In-reply-to: morioka@jaist.ac.jp's message of 15 Nov 1993 00:48:47 +0900
Xref: galaxy.trc.rwcp.or.jp fj.mail:1526 fj.editor.mule:1035
X-originally-archived-at: http://galaxy.rwcp.or.jp/text/cgi-bin/newsarticle2?ng=fj.mail&nb=1526&hd=a
X-reformat-date: Mon, 18 Oct 2004 15:18:22 +0900
X-reformat-comment: Tabs were expanded into 4 column tabstops by the Galaxy's archiver. See http://katsu.watanabe.name/ancientfj/galaxy-format.html for more info.

In article <MORIOKA.93Nov15004847@is15e0s03.jaist.ac.jp>,
morioka@jaist.ac.jp ($B<i2,(B $BCNI'(B (MORIOKA Tomohiko)) writes:

>   mime/decode-message-header $B4X?t$O(B, unfolding(encode $B$5$l$?;~(B, $B@^$j(B
> $BJV$5$l$?$b$N$r85$KLa$9(B)$B$r;XDj$7$J$$$H(B, $B@5$7$/(B decode $B$7$J$$$H$$$&%P%0(B?
> $B$,$"$k$h$&$G$9(B.

mime $B$C$F(B space $B$,$"$C$?$+$I$&$+$rJ]B8$G$-$J$$$h$&$J5$$,$9$k$N(B
$B$G$9$,(B, $B$I$&$J$s$G$7$g$&(B?

$B$?$H$($P(B, 

.... $B4A;z(B $B2~9T6uGr(B $B4A;z(B

$B$,(B

.... MIME $B2~9T6uGr(B MIME

$B$H(B encode $B$5$l$?$N$H(B, 

.... $B4A;z4A;z(B

$B$,D9$9$.$F(B

.... MIME $B2~9T6uGr(B MIME

$B$H$J$C$?$N$N6hJL$,$D$+$J$$$s$8$c$J$$$+$H$$$&$3$H$G$9(B.  RFC
1542 $B$K$O(B, $BC1$K6h@Z$l$H=q$$$F$"$k$@$1$G85$+$i$"$C$?6uGr$H$N6h(B
     $BJL$K$D$$$F$N5-=R$O8+IU$1$i$l$^$;$s$G$7$?(B($BC5$7J}$,$o$k$$(B?).

>   $B$^$?(B, encoder $B$b4^$^$l$F$$$^$9$,(B, encode $B7k2L$,(B RFC 1522 $B$K0cH?$9$k(B
> $B$N$G(B encoder $B$O;HMQ$7$J$$J}$,NI$$$G$7$g$&(B.

$BA0$N(B version $B$G$b0l1~(B JIS X0208 $B$K$D$$$F$O:GBg(B 18 $BJ8;z$7$+(B 
encode $B$7$J$$$h$&$K$J$C$F$$$^$7$?$,(B, $B$b$&$9$3$7$^$H$b$K$7$^$7(B
$B$?(B.  tspecial $B$H6uGr0J30$N(B, $B4A;z$r4^$`J8;zNs$r(B encode $B8e$ND9$5(B
$B$r5$$K$7$J$,$i(B encode $B$5$;$F$^$9(B.

$B$=$l$G$b(B encode $B$N$[$&$O$"$^$j?.MQ$7$J$$$[$&$,$$$$$G$7$g$&(B. 
$B=q$$$?K\?M$,;H$C$F$^$;$s$+$i(B:).

# vc.el $B3Z$@$o(B:).
$B$($J$_(B $B$D$0$H$b(B
--- 1.681993/10/23 04:59:24
+++ mime-kit.el 1.741993/11/15 12:33:29
@@ -26,7 +26,7 @@
 ;;o us-ascii charset.
 ;; Please send bug report or suggestions to `enami@sys.ptg.sony.co.jp'.
 ;;
-;; $Id: mime-kit.el,v 1.68 1993/10/23 04:59:24 enami Rel $
+;; $Id: mime-kit.el,v 1.74 1993/11/15 12:33:29 enami Rel $
 ;;
 ;; o From ich@yh.ntts.co.jp (Kei Ichiki),
 ;;- 2 functions (mime/base64-encode-region,
@@ -35,13 +35,14 @@
 ;;
 
 (defconst mime/version
-  "$Id: mime-kit.el,v 1.68 1993/10/23 04:59:24 enami Rel $"
+  "$Id: mime-kit.el,v 1.74 1993/11/15 12:33:29 enami Rel $"
   "vesion of mime-kit.")
 (defun mime/version () (interactive) (message mime/version))
 
 ;;(defconst mime/tspecials "()<>@,;:\\\"/[]?.=")
 (defconst mime/tspecials "][()<>@,;:\\\"/?.=")
 (defconst mime/tspecials-regexp "[][()<>@,;:\\\"/?.=]")
+
 (defconst mime/charset-regexp "[A-Za-z0-9!#$%&'*+---^_`{}|~]")
 (defconst mime/base64-charset (concat "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
       "abcdefghijklmnopqrstuvwxyz"
@@ -109,6 +110,9 @@
    "\\)"
    (regexp-quote
     mime/encoded-word-end)))
+(defconst mime/max-word-length 75
+  "mime encoded word should not exceeds this.")
+
 
 ;;
 ;; utility functions
@@ -356,13 +360,11 @@
  (save-excursion (re-search-forward "\\cj" nil t)))
        (defun mime/iso8859-*-region-p ()
  (save-excursion (re-search-forward "\\cl" nil t)))
-       (defconst mime/encode-word-regexp-iso2022-jp
- ;; max 18 chars.  should include ASCII?
- (concat "\\(\\cj\\cj\\cj\\cj\\cj\\cj\\cj\\cj\\)?"
- "\\(\\cj\\cj\\cj\\cj\\)?"
- "\\(\\cj\\cj\\)?"
- "\\cj?\\cj?\\cj?\\cj"))
-       (defconst mime/encode-word-regexp-iso8859-* "\\S *\\cl+\\S *")
+       (defun mime/word-regexp (base)
+ (concat "[^" mime/tspecials " \t" "]*" base 
+ "[^" mime/tspecials " \t" "]*"))
+       (defconst mime/encode-word-regexp-iso2022-jp (mime/word-regexp"\\cj+"))
+       (defconst mime/encode-word-regexp-iso8859-* (mime/word-regexp "\\cl+"))
        (defconst mime/encode-word-regexp
  (concat "\\(" mime/encode-word-regexp-iso2022-jp
  "\\|" mime/encode-word-regexp-iso8859-* "\\)"))
@@ -381,6 +383,14 @@
  (let ((name (car (rassq lc mime/iso8859-charset))))
    (or name
        (error "invalid ISO 8859 leading char: 0x%02x" lc))))
+       (defun mime/encode-length-1 (prev char)
+ (let ((plc (char-leading-char (if prev prev lc-ascii)))
+       (lc (if char (char-leading-char char))))
+   (+ (if (eq plc lc) 0 3); designation
+      (cond ((null lc) 0)
+    ((= lc lc-jp) 2)
+    ((= lc lc-ascii) 1)
+    (t (error "unknown leading-char: %c" lc))))))
        )
       ((and (boundp 'NEMACS) NEMACS)
        (defun mime/convert-string-iso2022-to-emacs (string)
@@ -394,28 +404,43 @@
        (defun mime/iso8859-*-region-p () nil)
        (defun mime/convert-string-iso8859-*-to-emacs (charset string)
  (mime/quoted-encode-string string))
-       (defconst mime/encode-word-regexp-iso2022-jp "[\200-\377]+")
-       (defconst mime/encode-word-regexp
- mime/encode-word-regexp-iso2022-jp)
+       (defconst mime/encode-word-regexp-iso2022-jp "\\S *[\200-\377]+\\S *")
+       (defconst mime/encode-word-regexp mime/encode-word-regexp-iso2022-jp)
        (defun mime/quoted-encode-char (char)
  "Encode the CHAR into string with Quoted Printable method."
  (upcase (cond ((= char ?\040) "_")
        (t (format "=%02x" char)))))
+       (defun mime/encode-length-1 (prev char)
+ (let ((plc (if prev 128 0))
+       ;; 128 or nil
+       (lc (if char 128)))
+   (+ (if (eq plc lc) 0 3); designation
+      (cond ((null lc) 0)
+    ((= lc 128) 2)
+    ((= lc 0) 1)
+    (t (error "unknown leading-char: %c" lc))))))
        ))
 
-(defconst mime/iso2022-encode-max 18)
-(defun mime/iso2022-encode-max-chars (col)
-  "Maximum number of chars to fit COL columns."
-  (+ (/ (- (* (/ (- col 18) 4) 3) 8) 2) 1) )
+;; (mime/base64-encode-size 18)
+(defun mime/base64-encode-size (offset)
+  (* (/ (- mime/max-word-length offset) 4) 3))
+
+(defun mime/forward-maximum-encodable (max)
+  (catch 'break
+    (let ((prev nil)
+  (char nil)
+  (total 0))
+      (while (not (eobp))
+(setq char (following-char))
+(setq total (+ total (mime/encode-length-1 prev char)))
+(if (> (+ total (mime/encode-length-1 char nil)) max)
+    (throw 'break t))
+(setq prev char)
+(forward-char)))))
 
-(defun mime/encoded-size (begin end)
-  (interactive "r")
-  (mime/narrow-to-region begin end nil
-    (cond ((mime/iso2022-jp-region-p)
-   (+ (length "=?ISO-2022-JP?B??=")
-      (* (/ (+ (length (mime/convert-string-emacs-to-iso2022
-(buffer-substring begin end))) 2) 3) 4)))
-  (t 0))))
+(defun mime/preceeding-non-space ()
+  (save-excursion
+    (- (point) (progn (skip-chars-backward "^ \t") (point)))))
 
 ;; (mime/decode-encoded-word "=?ISO-8859-1?Q?*GAR=C7ONS*?=")
 ;; (mime/decode-encoded-word "=?ISO-2022-JP?B?GyRAOjRGI0stGyhK?=")
@@ -457,16 +482,18 @@
   (let ((decoded nil); decode result
 (last nil); last decoded point
 (result t))
-    (mime/narrow-to-region begin end t
+    (mime/narrow-to-region begin end nil
       (while (re-search-forward mime/encoded-word-regexp nil t)
 (setq begin (match-beginning 0)
-      end (match-end 0)
+      ;; end (match-end 0)
       decoded (condition-case error
   (mime/decode-encoded-word (mime/nth-buffer-string 0))
 (error (if (not mime/decode-quiet)
    (signal (car error) (cdr error)) ))))
 (if (not decoded)
     (setq result nil)
+  ;; delete after insert.
+  (save-excursion (insert decoded))
   (delete-region (if (and concatenate
   last
   ;; if there is only white space.
@@ -476,9 +503,8 @@
 (= begin (match-end 0)) )))
      last
    begin)
- end)
-  (insert decoded)
-  (setq last (point)) ))
+ (point))
+  (setq last (+ (length decoded) (point))) ))
       result)))
 
 ;; (mime/decode-string "ABC =?ISO-8859-1?Q?*GAR=C7ONS*?= DEF")
@@ -503,7 +529,7 @@
       (forward-line)
       (if (re-search-forward "^\\S " nil t)
   (match-beginning 0)
-(point)))))
+(point-max)))))
 
 (defun mime/decode-field (&optional quiet filling)
   "decode and refill a field at point."
@@ -536,20 +562,31 @@
   "Encoder to encode iso2022-jp word")
 
 ;;; functions contributed from K.Ichiki 18-Aug-1992
-(defun mime/encode-word-iso2022-jp (begin end)
+(defun mime/encode-word-iso2022-jp (begin end &optional offset)
   "Encode text between point and mark by base64 method."
   (interactive "*r")
-  (if (= begin end)
-      nil
-    (let* ((encoder mime/word-iso2022-jp-encoder)
-   (mnemonic (get encoder 'mime/encoder-mnemonic))
-   (string (funcall encoder
-    (mime/convert-string-emacs-to-iso2022 
-     (buffer-substring begin end) ))))
-      (delete-region begin end)
-      (insert mime/encoded-word-begin
-      "ISO-2022-JP" (format "?%c?" (upcase mnemonic)) string
-      mime/encoded-word-end))))
+  (let* ((encoder mime/word-iso2022-jp-encoder)
+ (mnemonic (get encoder 'mime/encoder-mnemonic))
+ (string nil)
+ ;; 18 == (length "=?iso-2022-jp?b??=")
+ (max (max (mime/base64-encode-size (+ 18 (or offset 0))))))
+    (if (>= 0 (mime/base64-encode-size 18)) (setq mime/max-word-length 75))
+    (mime/narrow-to-region begin end t
+      (goto-char (point-min))
+      (while (not (eobp))
+(mime/forward-maximum-encodable (- max (mime/preceeding-non-space)))
+(if (= (point) (point-min))
+    nil
+  (setq string (funcall encoder
+(mime/convert-string-emacs-to-iso2022 
+ (buffer-substring (point-min) (point)))))
+  (delete-region (point-min) (point))
+  (insert mime/encoded-word-begin
+  "ISO-2022-JP" (format "?%c?" (upcase mnemonic)) string
+  mime/encoded-word-end)
+  (or (eobp) (insert ?\040)))
+(setq max (mime/base64-encode-size 18))
+(narrow-to-region (point) (point-max)) ))))
 
 ;; (mime/iso8859-leader lc-ascii)
 ;; (mime/iso8859-leader lc-ltn1)
@@ -559,7 +596,7 @@
 
 (defun mime/iso8859-insert-leader (begin end leading-char)
   (interactive "r\nn")
-  (mime/narrow-to-region begin end t
+  (mime/narrow-to-region begin end nil
     (mime/insert-at (point-min) (mime/iso8859-leader leading-char))
     (mime/insert-at (point-max) mime/encoded-word-end)))
 
@@ -567,15 +604,16 @@
   "Encoder to encode iso8859-* word (now fix to Q)")
 ;; (mime/modify-string "*GAR\201\307ONS*" (mime/encode-buffer-iso8859-*))
 ;; (mime/modify-string "abcdef" (mime/encode-buffer-iso8859-*))
-(defun mime/encode-word-iso8859-* (begin end)
+(defun mime/encode-word-iso8859-* (begin end &optional offset)
   "Encode the word includes iso-8859-* character with Qouted Printable
 Encoding.  The word is indicated by region from BEGIN to END.  So white
 space shouldn't be included."
   (interactive "*r")
-  (mime/narrow-to-region begin end t
+  (mime/narrow-to-region begin end nil
     (let ((leading-char nil)
   (char nil)
-  (max (- 75 (length "=?ISO-8859-*?Q??=")))
+  (max (- mime/max-word-length
+  (length "=?ISO-8859-*?Q??=") (or offset 0)))
   (regexp (concat "\\(\\cl\\|" mime/tspecials-regexp "\\)")))
       ;; \cl is category latin.
       (while (re-search-forward regexp nil t)
@@ -586,26 +624,31 @@
       (goto-char (+ max (point-min)))
       (mime/iso8859-insert-leader (point-min) (point) leading-char)
       (insert ?\040)
-      (narrow-to-region (point) (point-max)))
+      (narrow-to-region (point) (point-max))
+      (setq max (- mime/max-word-length (length "=?ISO-8859-*?Q??="))))
   (setq char (following-char))
   (if (or (null leading-char)
   (= leading-char (char-leading-char char)))
       nil
     (mime/iso8859-insert-leader (point-min) (point) leading-char)
     (insert ?\040)
-    (narrow-to-region (point) (point-max)))
+    (narrow-to-region (point) (point-max))
+    (setq max (- mime/max-word-length (length "=?ISO-8859-*?Q??="))))
   (setq leading-char (char-leading-char char))
-  (delete-char 1)
-  (insert (mime/quoted-encode-char char)) ))
+  ;; delete after insert.
+  (insert (mime/quoted-encode-char char))
+  (delete-char 1) ))
       (if leading-char
   (mime/iso8859-insert-leader (point-min) (point-max) leading-char)))))
 
 (defun mime/encode-buffer-iso8859-* ()
   (mime/encode-word-iso8859-* (point-min) (point-max)) )
 
-(defun mime/encode-word (begin end)
+(defun mime/encode-word (begin end &optional offset)
   (interactive "*r")
-  (mime/narrow-to-region begin end t
+  (mime/narrow-to-region begin end nil
+    ;;(goto-char (point-max)) (insert ?\040)
+    ;;(goto-char (point-min)) (insert ?\040)
     (funcall (cond ((mime/iso2022-jp-region-p)
     (function mime/encode-word-iso2022-jp))
    ((mime/iso8859-*-region-p)
@@ -613,33 +656,38 @@
    (t
     ;; will encode as US ASCII
     (function mime/encode-word-iso8859-*)))
-     (point-min) (point-max))))
+     (point-min) (point-max) offset)))
 
 ;;;###autoload
-(defun mime/encode-region (begin end)
-  "Encode the region from BEGIN to END by Base64 or Quoted Printable method."
+(defun mime/encode-region (begin end &optional offset)
+  "Encode the region from BEGIN to END by Base64 or Quoted Printable method.
+If optional third argument OFFSET are non nil, consider first column position."
   (interactive "r")
-  (mime/narrow-to-region begin end t
+  (mime/narrow-to-region begin end nil
     (while (re-search-forward mime/encode-word-regexp nil t)
-      (setq begin (match-beginning 0) end (match-end 0))
-      (if (looking-at mime/encode-word-regexp)
-  (insert ?\040))
-      (mime/encode-word begin end))))
+      (mime/encode-word (match-beginning 0) (match-end 0)
+(if offset
+    (save-excursion
+      (save-restriction 
+(widen)
+(goto-char begin)
+(current-column))))))))
 
 ;; (mime/encode-string "ABC *GAR\201\307ONS* DEF")
 ;;;###autoload
-(defun mime/encode-string (string)
+(defun mime/encode-string (string &optional offset)
   "Encode the STRING by Base64 or Quoted Printable method."
   (mime/modify-string string
-    (mime/encode-region (point-min) (point-max)) ))
+    (mime/encode-region (point-min) (point-max) offset) ))
 
 (defun mime/encode-field ()
   "encode and refill a field at point."
   (let ((at (point)))
     (mime/narrow-to-region (point-min) (point-max) nil
       (mime/narrow-to-field at)
-      (mime/encode-region (point-min) (point-max))
-      (let ((fill-prefix " "))
+      (mime/encode-region (point-min) (point-max) t)
+      (let ((fill-prefix " ")
+    (fill-column (1+ mime/max-word-length)))
 (fill-region-as-paragraph (point-min) (point-max)) ))))
 
 ;;;###autoload
