MEL 1.6.
[elisp/flim.git] / mel-q.el
1 ;;;
2 ;;; $Id: mel-q.el,v 1.5 1995/06/26 05:56:39 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       (while (re-search-forward "^.*$" nil t)
110         (replace-match
111          (quoted-printable-encode-string
112           (buffer-substring (match-beginning 0)(match-end 0))
113           ))
114         ))))
115
116 (defun quoted-printable-internal-decode-region (beg end)
117   (save-excursion
118     (save-restriction
119       (narrow-to-region beg end)
120       (goto-char (point-min))
121       (while (re-search-forward "=\n" nil t)
122         (replace-match "")
123         )
124       (goto-char (point-min))
125       (let (b e str)
126         (while (re-search-forward quoted-printable-octet-regexp nil t)
127           (setq b (match-beginning 0))
128           (setq e (match-end 0))
129           (setq str (buffer-substring b e))
130           (replace-match (quoted-printable-decode-string str))
131           ))
132       )))
133
134 (cond ((boundp 'MULE)
135        (define-program-coding-system
136          nil (car quoted-printable-external-encoder) *noconv*)
137        (define-program-coding-system
138          nil (car quoted-printable-external-decoder) *noconv*)
139        )
140       ((boundp 'NEMACS)
141        (define-program-kanji-code
142          nil (car quoted-printable-external-encoder) 0)
143        (define-program-kanji-code
144          nil (car quoted-printable-external-decoder) 0)
145        ))
146
147 (defun quoted-printable-external-encode-region (beg end)
148   (save-excursion
149     (apply (function call-process-region)
150            beg end (car quoted-printable-external-encoder)
151            t t nil (cdr quoted-printable-external-encoder))
152     ))
153
154 (defun quoted-printable-external-decode-region (beg end)
155   (save-excursion
156     (apply (function call-process-region)
157            beg end (car quoted-printable-external-decoder)
158            t t nil (cdr quoted-printable-external-decoder))
159     ))
160
161 (defun quoted-printable-encode-region (beg end)
162   (interactive "r")
163   (if (and quoted-printable-internal-encoding-limit
164            (> (- end beg) quoted-printable-internal-encoding-limit))
165       (quoted-printable-external-encode-region beg end)
166     (quoted-printable-internal-encode-region beg end)
167     ))
168
169 (defun quoted-printable-decode-region (beg end)
170   (interactive "r")
171   (if (and quoted-printable-internal-decoding-limit
172            (> (- end beg) quoted-printable-internal-decoding-limit))
173       (quoted-printable-external-decode-region beg end)
174     (quoted-printable-internal-decode-region beg end)
175     ))
176
177
178 ;;; @ Q-encoding encode/decode string
179 ;;;
180
181 (defun q-encoding-encode-string-for-text (str)
182   (mapconcat (function
183               (lambda (chr)
184                 (cond ((eq chr 32) "_")
185                       ((or (< chr 32) (< 126 chr) (eq chr ?=))
186                        (quoted-printable-quote-char chr)
187                        )
188                       (t (char-to-string chr))
189                       )))
190              str ""))
191
192 (defun q-encoding-encode-string-for-comment (str)
193   (mapconcat (function
194               (lambda (chr)
195                 (cond ((eq chr 32) "_")
196                       ((or (< chr 32) (< 126 chr)
197                            (memq chr '(?= ?\( ?\) ?\\))
198                            )
199                        (quoted-printable-quote-char chr)
200                        )
201                       (t (char-to-string chr))
202                       )))
203              str ""))
204
205 (defun q-encoding-encode-string-for-phrase (str)
206   (mapconcat (function
207               (lambda (chr)
208                 (cond ((or (and (<= ?A chr)(<= chr ?Z))
209                            (and (<= ?a chr)(<= chr ?z))
210                            (and (<= ?0 chr)(<= chr ?9))
211                            (memq chr '(?! ?* ?+ ?- ?/))
212                            )
213                        (char-to-string chr)
214                        )
215                       (t (quoted-printable-quote-char chr))
216                       )))
217              str ""))
218
219 (defun q-encoding-encode-string (str &optional mode)
220   (cond ((eq mode 'text)
221          (q-encoding-encode-string-for-text str)
222          )
223         ((eq mode 'comment)
224          (q-encoding-encode-string-for-comment str)
225          )
226         ((eq mode 'phrase)
227          (q-encoding-encode-string-for-phrase str)
228          )
229         (t (quoted-printable-encode-string str))
230         ))
231
232 (defun q-encoding-decode-string (str)
233   (let (q h l)
234     (mapconcat (function
235                 (lambda (chr)
236                   (cond ((eq chr ?_) " ")
237                         ((eq chr ?=)
238                          (setq q t)
239                          "")
240                         (q (setq h (cond ((<= ?a chr) (+ (- chr ?a) 10))
241                                          ((<= ?A chr) (+ (- chr ?A) 10))
242                                          ((<= ?0 chr) (- chr ?0))
243                                          ))
244                            (setq q nil)
245                            "")
246                         (h (setq l (cond ((<= ?a chr) (+ (- chr ?a) 10))
247                                          ((<= ?A chr) (+ (- chr ?A) 10))
248                                          ((<= ?0 chr) (- chr ?0))
249                                          ))
250                            (prog1
251                                (char-to-string (logior (ash h 4) l))
252                              (setq h nil)
253                              )
254                            )
255                         (t (char-to-string chr))
256                         )))
257                str "")))
258
259
260 ;;; @@ etc
261 ;;;
262
263 (defun q-encoding-encoded-length (string &optional mode)
264   (let ((l 0)(i 0)(len (length string)) chr)
265     (while (< i len)
266       (setq chr (elt string i))
267       (if (string-match "[A-Za-z0-9!*+/=_---]" (char-to-string chr))
268           (setq l (+ l 1))
269         (setq l (+ l 3))
270         )
271       (setq i (+ i 1)) )
272     l))
273
274
275 ;;; @ end
276 ;;;
277
278 (provide 'qprint)