;;; mel-zip.el --- bzip2-64 encoder/decoder, etc.

;; Copyleft (^^) 1999 Katsumi Yamaoka

;; Author: Katsumi Yamaoka <yamaoka@jpl.org>
;; Created: 1999/09/30
;; Revised: 1999/10/01
;; Keywords: x-bzip-2-64, x-rot13-47-48

;; This file is not part of any packages.

;;; Commentary:

;; $B$3$N%U%!%$%k$K$O(B x-bzip-2-64 $B$J5-;v$J$I$r(B FLIM $B$d(B SEMI $B$HJ;MQ$7$F(B
;; encode/decode $B$9$k$?$a$N%W%m%0%i%`$,4^$^$l$F$$$^$9!#$3$l$r;H$C$F(B
;; encode $B$7$?5-;v$rFI$a$k?M$O8B$i$l$F$$$^$9$N$G!"@dBP$KMpMQ$7$J$$$G(B
;; $B2<$5$$!#;H$$J}$O<!$NDL$j$G$9!#(B

;; 1. $B%$%s%9%H!<%k(B
;;    $B$3$N%U%!%$%k$rE,Ev$J(B load-path $B$N%G%#%l%/%H%j$K%3%T!<$7$F!"(BM-x
;;    byte-compile-file $B$7$F2<$5$$!#$=$7$F(B .emacs $B%U%!%$%k$N$I$3$+$K(B

;;	(require 'mel-zip)

;;    $B$H$$$&0l9T$rDI2C$7$F2<$5$$!#(B

;; 2. $B%(%s%3!<%I$NJ}K!(B
;;    C-c C-c $B$GAw?.$9$kA0$K9T$J$$$^$9!#(B
;;    $B$^$:!"%(%s%3!<%I$9$k%F%-%9%H$r(B text/plain $B$J%Q!<%H$H$7$FIaDL$K(B
;;    $B:n$C$F2<$5$$!#$=$7$F!"$=$N%F%-%9%H$N$I$3$+$G(B M-x zip-encode $B$H(B
;;    $B%?%$%W$7$F!"?R$M$i$l$?$3$H$KEz$($F2<$5$$!#(B

;;; Code:

(require 'mel)
(require 'mime-def)
(require 'path-util)

(defvar mel-zip-gzip-program (exec-installed-p "gzip"))
(defvar mel-zip-bzip2-program (exec-installed-p "bzip2"))

(defun bzip2-64-external-encode-region (start end)
  (interactive "*r")
  (if mel-zip-bzip2-program
      (save-restriction
	(narrow-to-region start end)
	(as-binary-process
	 (call-process-region start end mel-zip-bzip2-program t t))
	(funcall (mel-find-function 'mime-encode-region "base64")
		 (point-min) (point-max))
	(goto-char (point-min))
	(while (search-forward "\r\n" nil t)
	  (replace-match "\n")))))

(defun bzip2-64-external-decode-region (start end)
  (interactive "*r")
  (if mel-zip-bzip2-program
      (save-restriction
	(narrow-to-region start end)
	(funcall (mel-find-function 'mime-decode-region "base64")
		 start end)
	(as-binary-process
	 (call-process-region (point-min) (point-max)
			      mel-zip-bzip2-program t t nil "-d")))))

(defun bzip2-64-encode-string (string)
  (with-temp-buffer
    (insert string)
    (bzip2-64-external-encode-region (point-min) (point-max))
    (buffer-string)))

(defun bzip2-64-decode-string (string)
  (with-temp-buffer
    (insert string)
    (bzip2-64-external-decode-region (point-min) (point-max))
    (buffer-string)))

;;(mel-define-method-function (mime-encode-region start end (nil "x-bzip2-64"))
;;			    'bzip2-64-external-encode-region)
;;(mel-define-method-function (mime-decode-region start end (nil "x-bzip2-64"))
;;			    'bzip2-64-external-decode-region)
(mel-define-method-function (mime-encode-string string (nil "x-bzip2-64"))
			    'bzip2-64-encode-string)
(mel-define-method-function (mime-decode-string string (nil "x-bzip2-64"))
			    'bzip2-64-decode-string)


(eval-after-load "mime-edit"
  '(let ((text (assoc "text" mime-content-types))
;	 (application (assoc "application" mime-content-types))
;	 (image (assoc "image" mime-content-types))
	 )
     ;; x-rot13-47-48
     (or (assoc "x-rot13-47-48" text)
	 (setq text (append text '(("x-rot13-47-48")))))
;     ;; utf-8
;     (or (cdr (assoc "charset" (cdr (assoc "plain" text))))
;	 (if (find-coding-system 'utf-8)
;	     (set-alist 'text "plain"
;			'(("charset" "" "ISO-2022-JP" "US-ASCII"
;			   "ISO-8859-1" "ISO-8859-8" "UTF-8")))))
     (set-alist 'mime-content-types "text" (cdr text))
;     ;; x-patch
;     (or (assoc "x-patch" application)
;	 (setq application (append application '(("x-patch")))))
;     (set-alist 'mime-content-types "application" (cdr application))
;     (or (member "x-patch" (assoc "\\.diff$\\|\\.patch$" mime-file-types))
;	 (set-alist 'mime-file-types "\\.diff$\\|\\.patch$"
;		    '("application" "x-patch" (("type" . "patch"))
;		      nil
;		      "attachment" (("filename" . file)))))
;     ;; x-xpixmap
;     (or (assoc "x-xpixmap" image)
;	 (set-alist 'mime-content-types "image"
;		    (append (cdr image) '(("x-xpixmap")))))
     ))

;(eval-after-load "mime-view"
;  '(ctree-set-calist-strictly
;    'mime-preview-condition
;    '((type . application) (subtype . x-patch)
;      (body . visible)
;      (body-presentation-method . mime-display-text/plain))))


(defalias 'zip-encode 'mel-zip-manual-encode-at-point)

(autoload 'gzip64-external-encode-region "mel-g" nil t)

(defun mel-zip-manual-encode-at-point (subtype encoding)
  (interactive
   (list (completing-read "What content subtype: (default plain) "
			  '(("plain") ("x-rot13-47-48"))
			  nil t)
	 (completing-read "What transfer encoding: (default x-gzip64) "
			  '(("x-gzip64") ("x-bzip2-64"))
			  nil t
			  ;; "x-"
			  )))
  (if (zerop (length subtype))
      (setq subtype "plain"))
  (if (zerop (length encoding))
      (setq encoding "x-gzip64"))
  (let ((start (cond ((re-search-backward mime-edit-tag-regexp nil t)
		      (cons (match-beginning 0) (goto-char (match-end 0))))
		     ((search-backward (format "\n%s\n"
					       mail-header-separator) nil t)
		      (goto-char (match-end 0))
		      (prog1
			  (cons (point) (point))
			(insert "\n")))
		     (t (error "No tag or separator."))))
	(end (if (re-search-forward mime-edit-tag-regexp nil t)
		 (match-beginning 0)
	       (point-max)))
	charset cs)
    (save-window-excursion
      (save-restriction
	(narrow-to-region (1+ (cdr start)) end)
	(if (string-equal "x-rot13-47-48" subtype)
	    (mule-caesar-region (point-min) (point-max)))
	(setq charset (detect-mime-charset-region (point-min) (point-max)))
	(if (eq 'us-ascii charset)
	    nil
	  (if (or (not (find-coding-system 'utf-8))
		  (string-equal "x-rot13-47-48" subtype))
	      (setq cs charset)
	    (setq cs (completing-read
		      (format "What charset: (default \"%s\") " charset)
		      (list (list (symbol-name charset)) '("utf-8"))
		      nil t)
		  cs (if (zerop (length cs))
			 charset
		       (intern cs))))
	  (encode-mime-charset-region (point-min) (point-max) cs))
	(if (string-equal "x-gzip64" encoding)
	    (gzip64-external-encode-region (point-min) (point-max))
	  (bzip2-64-external-encode-region (point-min) (point-max)))
	(goto-char (point-max))
	(or (bolp) (insert "\n"))
	(if (and (not cs) (string-equal "x-rot13-47-48" subtype))
	    (mule-caesar-region (point-min) (point-max)))))
    (save-excursion
      (goto-char (car start))
      (delete-region (car start) (cdr start))
      (insert "--[[text/" subtype
	      (if cs
		  (concat "; charset=" (upcase (symbol-name cs)))
		"")
	      "][" encoding "]]"))))

(provide 'mel-zip)

;; mel-zip.el ends here
