+;;; @ Quoted-Printable decoder
+;;;
+
+(defsubst quoted-printable-hex-char-to-num (chr)
+ (cond ((<= ?a chr) (+ (- chr ?a) 10))
+ ((<= ?A chr) (+ (- chr ?A) 10))
+ ((<= ?0 chr) (- chr ?0))
+ ))
+
+(defun quoted-printable-internal-decode-region (start end)
+ (save-excursion
+ (save-restriction
+ (narrow-to-region start end)
+ (goto-char (point-min))
+ (while (search-forward "=" nil t)
+ (let ((beg (match-beginning 0)))
+ (cond ((looking-at "\n")
+ (delete-region beg (match-end 0))
+ )
+ ((looking-at
+ `,(concat "[" quoted-printable-hex-chars
+ "][" quoted-printable-hex-chars "]"))
+ (let* ((end (match-end 0))
+ (hex (buffer-substring (match-beginning 0) end)))
+ (delete-region beg end)
+ (insert
+ (logior
+ (ash (quoted-printable-hex-char-to-num (aref hex 0)) 4)
+ (quoted-printable-hex-char-to-num (aref hex 1))))
+ ))
+ (t
+ ;; invalid
+ ))
+ )))))
+
+(defvar quoted-printable-external-decoder '("mmencode" "-q" "-u")
+ "*list of quoted-printable decoder program name and its arguments.")
+
+(defun quoted-printable-external-decode-region (start end)
+ (save-excursion
+ (as-binary-process
+ (apply (function call-process-region)
+ start end (car quoted-printable-external-decoder)
+ t t nil (cdr quoted-printable-external-decoder))
+ )))
+
+(defun quoted-printable-internal-decode-string (string)
+ "Decode STRING which is encoded in quoted-printable, and return the result."
+ (with-temp-buffer
+ (insert string)
+ (quoted-printable-internal-decode-region (point-min)(point-max))
+ (buffer-string)))
+
+(defun quoted-printable-external-decode-string (string)
+ "Decode STRING which is encoded in quoted-printable, and return the result."
+ (with-temp-buffer
+ (insert string)
+ (quoted-printable-external-decode-region (point-min)(point-max))
+ (buffer-string)))
+
+(defvar quoted-printable-external-decoder-option-to-specify-file '("-o")
+ "*list of options of quoted-printable decoder program to specify file.")
+
+(defun quoted-printable-external-write-decoded-region (start end filename)
+ "Decode and write current region encoded by quoted-printable into FILENAME.
+START and END are buffer positions."
+ (interactive
+ (list (region-beginning) (region-end)
+ (read-file-name "Write decoded region to file: ")))
+ (as-binary-process
+ (apply (function call-process-region)
+ start end (car quoted-printable-external-decoder)
+ nil nil nil
+ (append (cdr quoted-printable-external-decoder)
+ quoted-printable-external-decoder-option-to-specify-file
+ (list filename))
+ )))
+
+\f