mel of MEL 1.9.
[elisp/flim.git] / mel-q.el
1 ;;;
2 ;;; $Id: mel-q.el,v 1.9 1995/09/09 05:14:23 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 ((or (< chr 32) (< 126 chr) (eq chr ?=))
52                          (if (>= i 73)
53                              (progn
54                                (setq i 0)
55                                (concat "=\n" (quoted-printable-quote-char chr))
56                                )
57                            (progn
58                              (setq i (+ i 3))
59                              (quoted-printable-quote-char chr)
60                              )))
61                         (t (if (>= i 75)
62                                (progn
63                                  (setq i 0)
64                                  (concat "=\n" (char-to-string chr))
65                                  )
66                              (progn
67                                (setq i (1+ i))
68                                (char-to-string chr)
69                                )))
70                         )))
71                str "")))
72
73 (defun quoted-printable-decode-string (str)
74   (let (q h l)
75     (mapconcat (function
76                 (lambda (chr)
77                   (cond ((eq chr ?=)
78                          (setq q t)
79                          "")
80                         (q (setq h
81                                  (cond ((<= ?a chr) (+ (- chr ?a) 10))
82                                        ((<= ?A chr) (+ (- chr ?A) 10))
83                                        ((<= ?0 chr) (- chr ?0))
84                                        ))
85                            (setq q nil)
86                            "")
87                         (h (setq l (cond ((<= ?a chr) (+ (- chr ?a) 10))
88                                          ((<= ?A chr) (+ (- chr ?A) 10))
89                                          ((<= ?0 chr) (- chr ?0))
90                                          ))
91                            (prog1
92                                (char-to-string (logior (ash h 4) l))
93                              (setq h nil)
94                              )
95                            )
96                         (t (char-to-string chr))
97                         )))
98                str "")))
99
100
101 ;;; @@ Quoted-Printable encode/decode region
102 ;;;
103
104 (defun quoted-printable-internal-encode-region (beg end)
105   (save-excursion
106     (save-restriction
107       (narrow-to-region beg end)
108       (goto-char (point-min))
109       (catch 'tag
110         (let (b e str)
111           (while t
112             (beginning-of-line) (setq b (point))
113             (end-of-line)       (setq e (point))
114             (if (< b e)
115                 (progn
116                   (setq str (buffer-substring b e))
117                   (delete-region b e)
118                   (insert (quoted-printable-encode-string str))
119                   ))
120             (if (eobp)
121                 (throw 'tag nil)
122               )
123             (forward-char 1)
124             )))
125       )))
126
127 (cond ((boundp 'MULE)
128        (define-program-coding-system
129          nil (car quoted-printable-external-encoder) *noconv*)
130        (define-program-coding-system
131          nil (car quoted-printable-external-decoder) *noconv*)
132        )
133       ((boundp 'NEMACS)
134        (define-program-kanji-code
135          nil (car quoted-printable-external-encoder) 0)
136        (define-program-kanji-code
137          nil (car quoted-printable-external-decoder) 0)
138        ))
139
140 (defun quoted-printable-external-encode-region (beg end)
141   (save-excursion
142     (apply (function call-process-region)
143            beg end (car quoted-printable-external-encoder)
144            t t nil (cdr quoted-printable-external-encoder))
145     ))
146
147 (defun quoted-printable-external-decode-region (beg end)
148   (save-excursion
149     (apply (function call-process-region)
150            beg end (car quoted-printable-external-decoder)
151            t t nil (cdr quoted-printable-external-decoder))
152     ))
153
154 (defun quoted-printable-encode-region (beg end)
155   (interactive "r")
156   (if (and quoted-printable-internal-encoding-limit
157            (> (- end beg) quoted-printable-internal-encoding-limit))
158       (quoted-printable-external-encode-region beg end)
159     (quoted-printable-internal-encode-region beg end)
160     ))
161
162 (defun quoted-printable-decode-region (beg end)
163   (interactive "r")
164   (if (and quoted-printable-internal-decoding-limit
165            (> (- end beg) quoted-printable-internal-decoding-limit))
166       (quoted-printable-external-decode-region beg end)
167     (quoted-printable-internal-decode-region beg end)
168     ))
169
170
171 ;;; @ Q-encoding encode/decode string
172 ;;;
173
174 (defun q-encoding-encode-string-for-text (str)
175   (mapconcat (function
176               (lambda (chr)
177                 (cond ((eq chr 32) "_")
178                       ((or (< chr 32) (< 126 chr) (eq chr ?=))
179                        (quoted-printable-quote-char chr)
180                        )
181                       (t (char-to-string chr))
182                       )))
183              str ""))
184
185 (defun q-encoding-encode-string-for-comment (str)
186   (mapconcat (function
187               (lambda (chr)
188                 (cond ((eq chr 32) "_")
189                       ((or (< chr 32) (< 126 chr)
190                            (memq chr '(?= ?\( ?\) ?\\))
191                            )
192                        (quoted-printable-quote-char chr)
193                        )
194                       (t (char-to-string chr))
195                       )))
196              str ""))
197
198 (defun q-encoding-encode-string-for-phrase (str)
199   (mapconcat (function
200               (lambda (chr)
201                 (cond ((eq chr 32) "_")
202                       ((or (and (<= ?A chr)(<= chr ?Z))
203                            (and (<= ?a chr)(<= chr ?z))
204                            (and (<= ?0 chr)(<= chr ?9))
205                            (memq chr '(?! ?* ?+ ?- ?/))
206                            )
207                        (char-to-string chr)
208                        )
209                       (t (quoted-printable-quote-char chr))
210                       )))
211              str ""))
212
213 (defun q-encoding-encode-string (str &optional mode)
214   (cond ((eq mode 'text)
215          (q-encoding-encode-string-for-text str)
216          )
217         ((eq mode 'comment)
218          (q-encoding-encode-string-for-comment str)
219          )
220         (t
221          (q-encoding-encode-string-for-phrase str)
222          )))
223
224 (defun q-encoding-decode-string (str)
225   (let (q h l)
226     (mapconcat (function
227                 (lambda (chr)
228                   (cond ((eq chr ?_) " ")
229                         ((eq chr ?=)
230                          (setq q t)
231                          "")
232                         (q (setq h (cond ((<= ?a chr) (+ (- chr ?a) 10))
233                                          ((<= ?A chr) (+ (- chr ?A) 10))
234                                          ((<= ?0 chr) (- chr ?0))
235                                          ))
236                            (setq q nil)
237                            "")
238                         (h (setq l (cond ((<= ?a chr) (+ (- chr ?a) 10))
239                                          ((<= ?A chr) (+ (- chr ?A) 10))
240                                          ((<= ?0 chr) (- chr ?0))
241                                          ))
242                            (prog1
243                                (char-to-string (logior (ash h 4) l))
244                              (setq h nil)
245                              )
246                            )
247                         (t (char-to-string chr))
248                         )))
249                str "")))
250
251
252 ;;; @@ etc
253 ;;;
254
255 (defun q-encoding-encoded-length (string &optional mode)
256   (let ((l 0)(i 0)(len (length string)) chr)
257     (while (< i len)
258       (setq chr (elt string i))
259       (if (string-match "[A-Za-z0-9!*+/=_---]" (char-to-string chr))
260           (setq l (+ l 1))
261         (setq l (+ l 3))
262         )
263       (setq i (+ i 1)) )
264     l))
265
266
267 ;;; @ end
268 ;;;
269
270 (provide 'mel-q)