mel of MEL 3.2.
[elisp/flim.git] / mel-q.el
1 ;;;
2 ;;; $Id: mel-q.el,v 3.0 1995/11/02 03:48:01 morioka Exp $
3 ;;;
4
5 ;;; @ constants
6 ;;;
7
8 (defconst quoted-printable-hex-chars "0123456789ABCDEF")
9 (defconst quoted-printable-octet-regexp
10   (concat "=[" quoted-printable-hex-chars
11           "][" quoted-printable-hex-chars "]"))
12
13
14 ;;; @ variables
15 ;;;
16
17 (defvar quoted-printable-external-encoder '("mmencode" "-q")
18   "*list of quoted-printable encoder program name and its arguments.")
19
20 (defvar quoted-printable-external-decoder '("mmencode" "-q" "-u")
21   "*list of quoted-printable decoder program name and its arguments.")
22
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.")
27
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.")
32
33
34 ;;; @ Quoted-Printable (Q-encode) encoder/decoder
35 ;;;
36
37 (defun quoted-printable-quote-char (chr)
38   (concat "="
39           (char-to-string (elt quoted-printable-hex-chars (ash chr -4)))
40           (char-to-string (elt quoted-printable-hex-chars (logand chr 15)))
41           ))
42
43
44 ;;; @@ Quoted-Printable encode/decode string
45 ;;;
46
47 (defun quoted-printable-encode-string (str)
48   (let ((i 0))
49     (mapconcat (function
50                 (lambda (chr)
51                   (cond ((eq chr ?\n)
52                          (setq i 0)
53                          "\n")
54                         ((or (< chr 32) (< 126 chr) (eq chr ?=))
55                          (if (>= i 73)
56                              (progn
57                                (setq i 3)
58                                (concat "=\n" (quoted-printable-quote-char chr))
59                                )
60                            (progn
61                              (setq i (+ i 3))
62                              (quoted-printable-quote-char chr)
63                              )))
64                         (t (if (>= i 75)
65                                (progn
66                                  (setq i 1)
67                                  (concat "=\n" (char-to-string chr))
68                                  )
69                              (progn
70                                (setq i (1+ i))
71                                (char-to-string chr)
72                                )))
73                         )))
74                str "")))
75
76 (defun quoted-printable-decode-string (str)
77   (let (q h l)
78     (mapconcat (function
79                 (lambda (chr)
80                   (cond ((eq chr ?=)
81                          (setq q t)
82                          "")
83                         (q (setq h
84                                  (cond ((<= ?a chr) (+ (- chr ?a) 10))
85                                        ((<= ?A chr) (+ (- chr ?A) 10))
86                                        ((<= ?0 chr) (- chr ?0))
87                                        ))
88                            (setq q nil)
89                            "")
90                         (h (setq l (cond ((<= ?a chr) (+ (- chr ?a) 10))
91                                          ((<= ?A chr) (+ (- chr ?A) 10))
92                                          ((<= ?0 chr) (- chr ?0))
93                                          ))
94                            (prog1
95                                (char-to-string (logior (ash h 4) l))
96                              (setq h nil)
97                              )
98                            )
99                         (t (char-to-string chr))
100                         )))
101                str "")))
102
103
104 ;;; @@ Quoted-Printable encode/decode region
105 ;;;
106
107 (defun quoted-printable-internal-encode-region (beg end)
108   (save-excursion
109     (save-restriction
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))
114         )
115       (or (bolp)
116           (insert "=\n")
117           )
118       )))
119
120 (defun quoted-printable-internal-decode-region (beg end)
121   (save-excursion
122     (save-restriction
123       (narrow-to-region beg end)
124       (goto-char (point-min))
125       (while (re-search-forward "=\n" nil t)
126         (replace-match "")
127         )
128       (goto-char (point-min))
129       (let (b e str)
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))
134           (delete-region b e)
135           (insert (quoted-printable-decode-string str))
136           ))
137       )))
138
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*)
144        )
145       ((boundp 'NEMACS)
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)
150        ))
151
152 (defun quoted-printable-external-encode-region (beg end)
153   (save-excursion
154     (save-restriction
155       (narrow-to-region beg end)
156       (let ((selective-display nil) ;Disable ^M to nl translation.
157             (mc-flag nil)      ;Mule
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))
162         )
163       ;; for OS/2
164       ;;   regularize line break code
165       (goto-char (point-min))
166       (while (re-search-forward "\r$" nil t)
167         (replace-match "")
168         )
169       )))
170
171 (defun quoted-printable-external-decode-region (beg end)
172   (save-excursion
173     (let ((selective-display nil) ;Disable ^M to nl translation.
174           (mc-flag nil)      ;Mule
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))
179       )))
180
181 (defun quoted-printable-encode-region (beg end)
182   (interactive "r")
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)
187     ))
188
189 (defun quoted-printable-decode-region (beg end)
190   (interactive "r")
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)
195     ))
196
197
198 ;;; @ Q-encoding encode/decode string
199 ;;;
200
201 (defun q-encoding-encode-string-for-text (str)
202   (mapconcat (function
203               (lambda (chr)
204                 (cond ((eq chr 32) "_")
205                       ((or (< chr 32) (< 126 chr) (eq chr ?=))
206                        (quoted-printable-quote-char chr)
207                        )
208                       (t (char-to-string chr))
209                       )))
210              str ""))
211
212 (defun q-encoding-encode-string-for-comment (str)
213   (mapconcat (function
214               (lambda (chr)
215                 (cond ((eq chr 32) "_")
216                       ((or (< chr 32) (< 126 chr)
217                            (memq chr '(?= ?\( ?\) ?\\))
218                            )
219                        (quoted-printable-quote-char chr)
220                        )
221                       (t (char-to-string chr))
222                       )))
223              str ""))
224
225 (defun q-encoding-encode-string-for-phrase (str)
226   (mapconcat (function
227               (lambda (chr)
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 '(?! ?* ?+ ?- ?/))
233                            )
234                        (char-to-string chr)
235                        )
236                       (t (quoted-printable-quote-char chr))
237                       )))
238              str ""))
239
240 (defun q-encoding-encode-string (str &optional mode)
241   (cond ((eq mode 'text)
242          (q-encoding-encode-string-for-text str)
243          )
244         ((eq mode 'comment)
245          (q-encoding-encode-string-for-comment str)
246          )
247         (t
248          (q-encoding-encode-string-for-phrase str)
249          )))
250
251 (defun q-encoding-decode-string (str)
252   (let (q h l)
253     (mapconcat (function
254                 (lambda (chr)
255                   (cond ((eq chr ?_) " ")
256                         ((eq chr ?=)
257                          (setq q t)
258                          "")
259                         (q (setq h (cond ((<= ?a chr) (+ (- chr ?a) 10))
260                                          ((<= ?A chr) (+ (- chr ?A) 10))
261                                          ((<= ?0 chr) (- chr ?0))
262                                          ))
263                            (setq q nil)
264                            "")
265                         (h (setq l (cond ((<= ?a chr) (+ (- chr ?a) 10))
266                                          ((<= ?A chr) (+ (- chr ?A) 10))
267                                          ((<= ?0 chr) (- chr ?0))
268                                          ))
269                            (prog1
270                                (char-to-string (logior (ash h 4) l))
271                              (setq h nil)
272                              )
273                            )
274                         (t (char-to-string chr))
275                         )))
276                str "")))
277
278
279 ;;; @@ etc
280 ;;;
281
282 (defun q-encoding-encoded-length (string &optional mode)
283   (let ((l 0)(i 0)(len (length string)) chr)
284     (while (< i len)
285       (setq chr (elt string i))
286       (if (string-match "[A-Za-z0-9!*+/=_---]" (char-to-string chr))
287           (setq l (+ l 1))
288         (setq l (+ l 3))
289         )
290       (setq i (+ i 1)) )
291     l))
292
293
294 ;;; @ end
295 ;;;
296
297 (provide 'mel-q)