+;;;###autoload
+(defun mail-quote-printable (string &optional wrapper)
+ "Convert a string to the \"quoted printable\" Q encoding.
+If the optional argument WRAPPER is non-nil,
+we add the wrapper characters =?ISO-8859-1?Q?....?=."
+ (let ((i 0) (result ""))
+ (save-match-data
+ (while (string-match "[?=\"\200-\377]" string i)
+ (setq result
+ (concat result (substring string i (match-beginning 0))
+ (upcase (format "=%02x"
+ (aref string (match-beginning 0))))))
+ (setq i (match-end 0)))
+ (if wrapper
+ (concat "=?ISO-8859-1?Q?"
+ result (substring string i)
+ "?=")
+ (concat result (substring string i))))))
+
+(defun mail-unquote-printable-hexdigit (char)
+ (setq char (upcase char))
+ (if (>= char ?A)
+ (+ (- char ?A) 10)
+ (- char ?0)))
+
+;;;###autoload
+(defun mail-unquote-printable (string &optional wrapper)
+ "Undo the \"quoted printable\" encoding.
+If the optional argument WRAPPER is non-nil,
+we expect to find and remove the wrapper characters =?ISO-8859-1?Q?....?=."
+ (save-match-data
+ (and wrapper
+ (string-match "\\`=\\?ISO-8859-1\\?Q\\?\\([^?]*\\)\\?" string)
+ (setq string (match-string 1 string)))
+ (let ((i 0) strings)
+ (while (string-match "=\\(..\\|\n\\)" string i)
+ (setq strings (cons (substring string i (match-beginning 0)) strings))
+ (unless (= (aref string (match-beginning 1)) ?\n)
+ (setq strings
+ (cons (make-string 1
+ (+ (* 16 (mail-unquote-printable-hexdigit
+ (aref string (match-beginning 1))))
+ (mail-unquote-printable-hexdigit
+ (aref string (1+ (match-beginning 1))))))
+ strings)))
+ (setq i (match-end 0)))
+ (apply 'concat (nreverse (cons (substring string i) strings))))))
+
+;;;###autoload
+(defun mail-unquote-printable-region (beg end &optional wrapper noerror)
+ "Undo the \"quoted printable\" encoding in buffer from BEG to END.
+If the optional argument WRAPPER is non-nil,
+we expect to find and remove the wrapper characters =?ISO-8859-1?Q?....?=.
+If NOERROR is non-nil, return t if successful."
+ (interactive "r\nP")
+ (let (failed)
+ (save-match-data
+ (save-excursion
+ (save-restriction
+ (narrow-to-region beg end)
+ (goto-char (point-min))
+ (when (and wrapper
+ (looking-at "\\`=\\?ISO-8859-1\\?Q\\?\\([^?]*\\)\\?"))
+ (delete-region (match-end 1) end)
+ (delete-region (point) (match-beginning 1)))
+ (while (re-search-forward "=\\(\\([0-9A-F][0-9A-F]\\)\\|[=\n]\\|..\\)" nil t)
+ (goto-char (match-end 0))
+ (cond ((= (char-after (match-beginning 1)) ?\n)
+ (replace-match ""))
+ ((= (char-after (match-beginning 1)) ?=)
+ (replace-match "="))
+ ((match-beginning 2)
+ (replace-match
+ (make-string 1
+ (+ (* 16 (mail-unquote-printable-hexdigit
+ (char-after (match-beginning 2))))
+ (mail-unquote-printable-hexdigit
+ (char-after (1+ (match-beginning 2))))))
+ t t))
+ (noerror
+ (setq failed t))
+ (t
+ (error "Malformed MIME quoted-printable message"))))
+ (not failed))))))
+
+(eval-when-compile (require 'rfc822))
+