Update FSF's address in GPL notices.
[elisp/flim.git] / mel-b-el.el
index 7426cc5..a16b412 100644 (file)
@@ -1,13 +1,13 @@
-;;; mel-b-el.el: Base64 encoder/decoder for GNU Emacs
+;;; mel-b-el.el --- Base64 encoder/decoder.
 
-;; Copyright (C) 1992,1995,1996,1997,1998 Free Software Foundation, Inc.
+;; Copyright (C) 1992,95,96,97,98,99,2001 Free Software Foundation, Inc.
 
 ;; Author: ENAMI Tsugutomo <enami@sys.ptg.sony.co.jp>
-;;         MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;;         MORIOKA Tomohiko <tomo@m17n.org>
 ;; Created: 1995/6/24
 ;; Keywords: MIME, Base64
 
-;; This file is part of MEL (MIME Encoding Library).
+;; This file is part of FLIM (Faithful Library about Internet Message).
 
 ;; This program is free software; you can redistribute it and/or
 ;; modify it under the terms of the GNU General Public License as
 ;; 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, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; along with this program; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Code:
 
-(require 'poe)
 (require 'mime-def)
+(eval-when-compile
+  ;; XXX: the macro `as-binary-process' should be provided when compiling.
+  (require 'pces))
 
 
 ;;; @ variables
@@ -48,7 +50,8 @@
   :type '(cons (file :tag "Command")(repeat :tag "Arguments" string)))
 
 (defcustom base64-external-decoder-option-to-specify-file '("-o")
-  "*list of options of base64 decoder program to specify file."
+  "*list of options of base64 decoder program to specify file.
+If the base64 decoder program does not have such option, set this as nil."
   :group 'base64
   :type '(repeat :tag "Arguments" string))
 
@@ -72,6 +75,26 @@ external decoder is called."
                 (integer :tag "Size")))
 
 
+;;; @ utility function
+;;;
+
+(defun pack-sequence (seq size)
+  "Split sequence SEQ into SIZE elements packs, and return list of packs.
+\[mel-b-el; tl-seq function]"
+  (let ((len (length seq))
+       (p 0)
+       dest unit)
+    (while (< p len)
+      (setq unit (cons (elt seq p) unit))
+      (setq p (1+ p))
+      (when (zerop (mod p size))
+       (setq dest (cons (nreverse unit) dest))
+       (setq unit nil)))
+    (if unit
+       (nreverse (cons (nreverse unit) dest))
+      (nreverse dest))))
+
+
 ;;; @ internal base64 encoder
 ;;;    based on base64 decoder by Enami Tsugutomo
 
@@ -84,33 +107,33 @@ external decoder is called."
   `(aref base64-characters ,n))
 
 (defun base64-encode-1 (pack)
-  (let ((a (car pack))
-       (b (nth 1 pack))
-       (c (nth 2 pack)))
-    (concat
-     (char-to-string (base64-num-to-char (ash a -2)))
-     (if b
-        (concat
-         (char-to-string
-          (base64-num-to-char (logior (ash (logand a 3) 4) (ash b -4))))
-         (if c
-             (concat
-              (char-to-string
-               (base64-num-to-char (logior (ash (logand b 15) 2) (ash c -6))))
-              (char-to-string (base64-num-to-char (logand c 63)))
-              )
-           (concat (char-to-string
-                    (base64-num-to-char (ash (logand b 15) 2))) "=")
-           ))
-       (concat (char-to-string
-               (base64-num-to-char (ash (logand a 3) 4))) "==")
-       ))))
-
-(defun-maybe base64-encode-string (string)
-  "Encode STRING to base64, and return the result."
-  (let ((len (length string))
-       (b 0)(e 57)
-       dest)
+  (let ((buf (make-string 4 ?=)))
+    (aset buf 0 (base64-num-to-char (ash (car pack) -2)))
+    (if (nth 1 pack)
+       (progn
+         (aset buf 1 (base64-num-to-char
+                      (logior (ash (logand (car pack) 3) 4)
+                              (ash (nth 1 pack) -4))))
+         (if (nth 2 pack)
+             (progn
+               (aset buf 2 (base64-num-to-char
+                            (logior (ash (logand (nth 1 pack) 15) 2)
+                                    (ash (nth 2 pack) -6))))
+               (aset buf 3 (base64-num-to-char
+                            (logand (nth 2 pack) 63))))
+           (aset buf 2 (base64-num-to-char
+                        (ash (logand (nth 1 pack) 15) 2)))))
+      (aset buf 1 (base64-num-to-char
+                  (ash (logand (car pack) 3) 4))))
+    buf))
+
+(defun-maybe base64-encode-string (string &optional no-line-break)
+  "Base64-encode STRING and return the result.
+Optional second argument NO-LINE-BREAK means do not break long lines
+into shorter lines."
+  (let* ((len (length string))
+        (b 0)(e 57)
+        (dest ""))
     (while (< e len)
       (setq dest
            (concat dest
@@ -118,34 +141,23 @@ external decoder is called."
                     (function base64-encode-1)
                     (pack-sequence (substring string b e) 3)
                     "")
-                   "\n"))
+                   (if (not no-line-break) "\n")))
       (setq b e
-           e (+ e 57)
-           )
-      )
-    (let* ((es (mapconcat
-               (function base64-encode-1)
-               (pack-sequence (substring string b) 3)
-               ""))
-          (m (mod (length es) 4))
-          )
-      (concat dest es (cond ((= m 3) "=")
-                           ((= m 2) "==")
-                           ))
-      )))
-
-(defun base64-internal-encode-region (beg end)
+           e (+ e 57)))
+    (concat dest
+           (mapconcat
+            (function base64-encode-1)
+            (pack-sequence (substring string b) 3)
+            ""))))
+
+(defun base64-internal-encode-region (beg end &optional no-line-break)
   (save-excursion
     (save-restriction
       (narrow-to-region beg end)
-      (let ((str (buffer-substring beg end)))
-       (delete-region beg end)
-       (insert (base64-encode-string str))
-       )
-      (or (bolp)
-         (insert "\n")
-         )
-      )))
+      (insert
+       (prog1
+          (base64-encode-string (buffer-substring beg end) no-line-break)
+        (delete-region beg end))))))
 
 
 ;;; @ internal base64 decoder
@@ -166,8 +178,7 @@ external decoder is called."
 
 (defsubst base64-internal-decode (string buffer)
   (let* ((len (length string))
-        (i 0)
-        (j 0)
+        (i 0)(j 0)
         v1 v2 v3)
     (catch 'tag
       (while (< i len)
@@ -187,12 +198,9 @@ external decoder is called."
                (if v4
                    (aset buffer (prog1 j (setq j (1+ j)))
                          (logior (lsh (logand v3 3) 6) v4))
-                 (throw 'tag nil)
-                 ))
-           (throw 'tag nil)
-           ))))
-    (substring buffer 0 j)
-    ))
+                 (throw 'tag nil)))
+           (throw 'tag nil)))))
+    (substring buffer 0 j)))
 
 (defun base64-internal-decode-string (string)
   (base64-internal-decode string (make-string (length string) 0)))
@@ -204,9 +212,10 @@ external decoder is called."
 (defun base64-internal-decode-region (beg end)
   (save-excursion
     (let ((str (string-as-unibyte (buffer-substring beg end))))
-      (delete-region beg end)
-      (goto-char beg)
-      (insert (base64-internal-decode str str)))))
+      (insert
+       (prog1
+          (base64-internal-decode str str)
+        (delete-region beg end))))))
 
 ;; (defun base64-internal-decode-region2 (beg end)
 ;;   (save-excursion
@@ -226,56 +235,63 @@ external decoder is called."
 ;;; @ external encoder/decoder
 ;;;
 
-(defun base64-external-encode-region (beg end)
+(defun base64-external-encode-region (beg end &optional no-line-break)
   (save-excursion
     (save-restriction
       (narrow-to-region beg end)
       (as-binary-process
        (apply (function call-process-region)
              beg end (car base64-external-encoder)
-             t t nil (cdr base64-external-encoder)))
+             t t nil
+             (cdr base64-external-encoder)))
       ;; for OS/2
       ;;   regularize line break code
       (goto-char (point-min))
       (while (re-search-forward "\r$" nil t)
        (replace-match ""))
-      )))
+      (if no-line-break
+         (progn
+           (goto-char (point-min))
+           (while (search-forward "\n" nil t)
+             (replace-match "")))))))
 
 (defun base64-external-decode-region (beg end)
   (save-excursion
     (as-binary-process
      (apply (function call-process-region)
            beg end (car base64-external-decoder)
-           t t nil (cdr base64-external-decoder)))
-    ))
+           t t nil
+           (cdr base64-external-decoder)))))
 
 (defun base64-external-decode-string (string)
   (with-temp-buffer
     (insert string)
     (as-binary-process
      (apply (function call-process-region)
-           (point-min) (point-max)
-           (car base64-external-decoder)
-           t t nil (cdr base64-external-decoder)))
+           (point-min)(point-max) (car base64-external-decoder)
+           t t nil
+           (cdr base64-external-decoder)))
     (buffer-string)))
 
 
 ;;; @ application interfaces
 ;;;
 
-(defun-maybe base64-encode-region (start end)
-  "Encode current region by base64.
-START and END are buffer positions.
+(defun-maybe base64-encode-region (start end &optional no-line-break)
+  "Base64-encode the region between START and END.
+Return the length of the encoded text.
+Optional third argument NO-LINE-BREAK means do not break long lines
+into shorter lines.
 This function calls internal base64 encoder if size of region is
 smaller than `base64-internal-encoding-limit', otherwise it calls
 external base64 encoder specified by `base64-external-encoder'.  In
 this case, you must install the program (maybe mmencode included in
 metamail or XEmacs package)."
-  (interactive "r")
+  (interactive "*r")
   (if (and base64-internal-encoding-limit
           (> (- end start) base64-internal-encoding-limit))
-      (base64-external-encode-region start end)
-    (base64-internal-encode-region start end)))
+      (base64-external-encode-region start end no-line-break)
+    (base64-internal-encode-region start end no-line-break)))
 
 (defun-maybe base64-decode-region (start end)
   "Decode current region by base64.
@@ -285,7 +301,7 @@ smaller than `base64-internal-decoding-limit', otherwise it calls
 external base64 decoder specified by `base64-external-decoder'.  In
 this case, you must install the program (maybe mmencode included in
 metamail or XEmacs package)."
-  (interactive "r")
+  (interactive "*r")
   (if (and base64-internal-decoding-limit
           (> (- end start) base64-internal-decoding-limit))
       (base64-external-decode-region start end)
@@ -298,7 +314,6 @@ smaller than `base64-internal-decoding-limit', otherwise it calls
 external base64 decoder specified by `base64-external-decoder'.  In
 this case, you must install the program (maybe mmencode included in
 metamail or XEmacs package)."
-  (interactive "r")
   (if (and base64-internal-decoding-limit
           (> (length string) base64-internal-decoding-limit))
       (base64-external-decode-string string)
@@ -318,8 +333,9 @@ metamail or XEmacs package)."
                            'base64-encode-string)
 
 (mel-define-method encoded-text-decode-string (string (nil "B"))
-  (if (and (string-match B-encoded-text-regexp string)
-          (string= string (match-string 0 string)))
+  (if (string-match (eval-when-compile
+                     (concat "\\`" B-encoded-text-regexp "\\'"))
+                   string)
       (base64-decode-string string)
     (error "Invalid encoded-text %s" string)))
 
@@ -328,21 +344,21 @@ metamail or XEmacs package)."
 It calls external base64 encoder specified by
 `base64-external-encoder'.  So you must install the program (maybe
 mmencode included in metamail or XEmacs package)."
-  (interactive (list (read-file-name "Insert encoded file: ")))
+  (interactive "*fInsert encoded file: ")
   (if (and base64-internal-encoding-limit
           (> (nth 7 (file-attributes filename))
              base64-internal-encoding-limit))
-      (apply (function call-process) (car base64-external-encoder)
-            filename t nil (cdr base64-external-encoder))
+      (apply (function call-process)
+            (car base64-external-encoder)
+            filename t nil
+            (cdr base64-external-encoder))
     (insert
      (base64-encode-string
       (with-temp-buffer
        (set-buffer-multibyte nil)
        (insert-file-contents-as-binary filename)
        (buffer-string))))
-    (or (bolp)
-       (insert "\n"))
-     ))
+    (or (bolp) (insert ?\n))))
 
 (mel-define-method-function (mime-insert-encoded-file filename (nil "base64"))
                            'base64-insert-encoded-file)
@@ -350,56 +366,34 @@ mmencode included in metamail or XEmacs package)."
 (defun base64-write-decoded-region (start end filename)
   "Decode and write current region encoded by base64 into FILENAME.
 START and END are buffer positions."
-  (interactive
-   (list (region-beginning) (region-end)
-        (read-file-name "Write decoded region to file: ")))
+  (interactive "*r\nFWrite decoded region to file: ")
   (if (and base64-internal-decoding-limit
           (> (- end start) base64-internal-decoding-limit))
-      (as-binary-process
-       (apply (function call-process-region)
-             start end (car base64-external-decoder)
-             nil nil nil
-             (append (cdr base64-external-decoder)
-                     base64-external-decoder-option-to-specify-file
-                     (list filename))))
+      (progn
+       (as-binary-process
+        (apply (function call-process-region)
+               start end (car base64-external-decoder)
+               (null base64-external-decoder-option-to-specify-file)
+               (unless base64-external-decoder-option-to-specify-file
+                 (list (current-buffer) nil))
+               nil
+               (delq nil
+                     (append
+                      (cdr base64-external-decoder)
+                      base64-external-decoder-option-to-specify-file
+                      (when base64-external-decoder-option-to-specify-file
+                        (list filename))))))
+       (unless base64-external-decoder-option-to-specify-file
+         (write-region-as-binary (point-min) (point-max) filename)))
     (let ((str (buffer-substring start end)))
       (with-temp-buffer
        (insert (base64-internal-decode-string str))
-       (write-region-as-binary (point-min) (point-max) filename)
-       ))))
+       (write-region-as-binary (point-min) (point-max) filename)))))
 
 (mel-define-method-function
  (mime-write-decoded-region start end filename (nil "base64"))
  'base64-write-decoded-region)
 
-       
-;;; @ etc
-;;;
-
-(defun pack-sequence (seq size)
-  "Split sequence SEQ into SIZE elements packs,
-and return list of packs. [mel-b-el; tl-seq function]"
-  (let ((len (length seq)) (p 0) obj
-       unit (i 0)
-       dest)
-    (while (< p len)
-      (setq obj (elt seq p))
-      (setq unit (cons obj unit))
-      (setq i (1+ i))
-      (if (= i size)
-         (progn
-           (setq dest (cons (reverse unit) dest))
-           (setq unit nil)
-           (setq i 0)
-           ))
-      (setq p (1+ p))
-      )
-    (if unit
-       (setq dest (cons (reverse unit) dest))
-      )
-    (reverse dest)
-    ))
-
 
 ;;; @ end
 ;;;