2 ;;; $Id: mel-q.el,v 3.0 1995/11/02 03:48:01 morioka Exp $
8 (defconst quoted-printable-hex-chars "0123456789ABCDEF")
9 (defconst quoted-printable-octet-regexp
10 (concat "=[" quoted-printable-hex-chars
11 "][" quoted-printable-hex-chars "]"))
17 (defvar quoted-printable-external-encoder '("mmencode" "-q")
18 "*list of quoted-printable encoder program name and its arguments.")
20 (defvar quoted-printable-external-decoder '("mmencode" "-q" "-u")
21 "*list of quoted-printable decoder program name and its arguments.")
23 (defvar quoted-printable-internal-encoding-limit 10000
24 "*limit size to use internal quoted-printable encoder.
25 If size of input to encode is larger than this limit,
26 external encoder is called.")
28 (defvar quoted-printable-internal-decoding-limit nil
29 "*limit size to use internal quoted-printable decoder.
30 If size of input to decode is larger than this limit,
31 external decoder is called.")
34 ;;; @ Quoted-Printable (Q-encode) encoder/decoder
37 (defun quoted-printable-quote-char (chr)
39 (char-to-string (elt quoted-printable-hex-chars (ash chr -4)))
40 (char-to-string (elt quoted-printable-hex-chars (logand chr 15)))
44 ;;; @@ Quoted-Printable encode/decode string
47 (defun quoted-printable-encode-string (str)
54 ((or (< chr 32) (< 126 chr) (eq chr ?=))
58 (concat "=\n" (quoted-printable-quote-char chr))
62 (quoted-printable-quote-char chr)
67 (concat "=\n" (char-to-string chr))
76 (defun quoted-printable-decode-string (str)
84 (cond ((<= ?a chr) (+ (- chr ?a) 10))
85 ((<= ?A chr) (+ (- chr ?A) 10))
86 ((<= ?0 chr) (- chr ?0))
90 (h (setq l (cond ((<= ?a chr) (+ (- chr ?a) 10))
91 ((<= ?A chr) (+ (- chr ?A) 10))
92 ((<= ?0 chr) (- chr ?0))
95 (char-to-string (logior (ash h 4) l))
99 (t (char-to-string chr))
104 ;;; @@ Quoted-Printable encode/decode region
107 (defun quoted-printable-internal-encode-region (beg end)
110 (narrow-to-region beg end)
111 (let ((str (buffer-substring beg end)))
112 (delete-region beg end)
113 (insert (quoted-printable-encode-string str))
120 (defun quoted-printable-internal-decode-region (beg end)
123 (narrow-to-region beg end)
124 (goto-char (point-min))
125 (while (re-search-forward "=\n" nil t)
128 (goto-char (point-min))
130 (while (re-search-forward quoted-printable-octet-regexp nil t)
131 (setq b (match-beginning 0))
132 (setq e (match-end 0))
133 (setq str (buffer-substring b e))
135 (insert (quoted-printable-decode-string str))
139 (cond ((boundp 'MULE)
140 (define-program-coding-system
141 nil (car quoted-printable-external-encoder) *noconv*)
142 (define-program-coding-system
143 nil (car quoted-printable-external-decoder) *noconv*)
146 (define-program-kanji-code
147 nil (car quoted-printable-external-encoder) 0)
148 (define-program-kanji-code
149 nil (car quoted-printable-external-decoder) 0)
152 (defun quoted-printable-external-encode-region (beg end)
155 (narrow-to-region beg end)
156 (let ((selective-display nil) ;Disable ^M to nl translation.
158 (kanji-flag nil)) ;NEmacs
159 (apply (function call-process-region)
160 beg end (car quoted-printable-external-encoder)
161 t t nil (cdr quoted-printable-external-encoder))
164 ;; regularize line break code
165 (goto-char (point-min))
166 (while (re-search-forward "\r$" nil t)
171 (defun quoted-printable-external-decode-region (beg end)
173 (let ((selective-display nil) ;Disable ^M to nl translation.
175 (kanji-flag nil)) ;NEmacs
176 (apply (function call-process-region)
177 beg end (car quoted-printable-external-decoder)
178 t t nil (cdr quoted-printable-external-decoder))
181 (defun quoted-printable-encode-region (beg end)
183 (if (and quoted-printable-internal-encoding-limit
184 (> (- end beg) quoted-printable-internal-encoding-limit))
185 (quoted-printable-external-encode-region beg end)
186 (quoted-printable-internal-encode-region beg end)
189 (defun quoted-printable-decode-region (beg end)
191 (if (and quoted-printable-internal-decoding-limit
192 (> (- end beg) quoted-printable-internal-decoding-limit))
193 (quoted-printable-external-decode-region beg end)
194 (quoted-printable-internal-decode-region beg end)
198 ;;; @ Q-encoding encode/decode string
201 (defun q-encoding-encode-string-for-text (str)
204 (cond ((eq chr 32) "_")
205 ((or (< chr 32) (< 126 chr) (eq chr ?=))
206 (quoted-printable-quote-char chr)
208 (t (char-to-string chr))
212 (defun q-encoding-encode-string-for-comment (str)
215 (cond ((eq chr 32) "_")
216 ((or (< chr 32) (< 126 chr)
217 (memq chr '(?= ?\( ?\) ?\\))
219 (quoted-printable-quote-char chr)
221 (t (char-to-string chr))
225 (defun q-encoding-encode-string-for-phrase (str)
228 (cond ((eq chr 32) "_")
229 ((or (and (<= ?A chr)(<= chr ?Z))
230 (and (<= ?a chr)(<= chr ?z))
231 (and (<= ?0 chr)(<= chr ?9))
232 (memq chr '(?! ?* ?+ ?- ?/))
236 (t (quoted-printable-quote-char chr))
240 (defun q-encoding-encode-string (str &optional mode)
241 (cond ((eq mode 'text)
242 (q-encoding-encode-string-for-text str)
245 (q-encoding-encode-string-for-comment str)
248 (q-encoding-encode-string-for-phrase str)
251 (defun q-encoding-decode-string (str)
255 (cond ((eq chr ?_) " ")
259 (q (setq h (cond ((<= ?a chr) (+ (- chr ?a) 10))
260 ((<= ?A chr) (+ (- chr ?A) 10))
261 ((<= ?0 chr) (- chr ?0))
265 (h (setq l (cond ((<= ?a chr) (+ (- chr ?a) 10))
266 ((<= ?A chr) (+ (- chr ?A) 10))
267 ((<= ?0 chr) (- chr ?0))
270 (char-to-string (logior (ash h 4) l))
274 (t (char-to-string chr))
282 (defun q-encoding-encoded-length (string &optional mode)
283 (let ((l 0)(i 0)(len (length string)) chr)
285 (setq chr (elt string i))
286 (if (string-match "[A-Za-z0-9!*+/=_---]" (char-to-string chr))