2 ;;; mel-q.el: Quoted-Printable encoder/decoder for GNU Emacs
4 ;;; Copyright (C) 1995 Free Software Foundation, Inc.
5 ;;; Copyright (C) 1995,1996 MORIOKA Tomohiko
7 ;;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
8 ;;; Maintainer: MORIOKA Tomohiko <morioka@jaist.ac.jp>
11 ;;; $Id: mel-q.el,v 3.1 1996/01/09 18:28:53 morioka Exp $
12 ;;; Keywords: MIME, Quoted-Printable
14 ;;; This file is part of MEL (MIME Encoding Library).
16 ;;; This program is free software; you can redistribute it and/or
17 ;;; modify it under the terms of the GNU General Public License as
18 ;;; published by the Free Software Foundation; either version 2, or
19 ;;; (at your option) any later version.
21 ;;; This program is distributed in the hope that it will be useful,
22 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
23 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 ;;; General Public License for more details.
26 ;;; You should have received a copy of the GNU General Public License
27 ;;; along with This program. If not, write to the Free Software
28 ;;; Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
36 (defconst quoted-printable-hex-chars "0123456789ABCDEF")
37 (defconst quoted-printable-octet-regexp
38 (concat "=[" quoted-printable-hex-chars
39 "][" quoted-printable-hex-chars "]"))
45 (defvar quoted-printable-external-encoder '("mmencode" "-q")
46 "*list of quoted-printable encoder program name and its arguments.")
48 (defvar quoted-printable-external-decoder '("mmencode" "-q" "-u")
49 "*list of quoted-printable decoder program name and its arguments.")
51 (defvar quoted-printable-internal-encoding-limit 10000
52 "*limit size to use internal quoted-printable encoder.
53 If size of input to encode is larger than this limit,
54 external encoder is called.")
56 (defvar quoted-printable-internal-decoding-limit nil
57 "*limit size to use internal quoted-printable decoder.
58 If size of input to decode is larger than this limit,
59 external decoder is called.")
62 ;;; @ Quoted-Printable (Q-encode) encoder/decoder
65 (defun quoted-printable-quote-char (chr)
67 (char-to-string (elt quoted-printable-hex-chars (ash chr -4)))
68 (char-to-string (elt quoted-printable-hex-chars (logand chr 15)))
72 ;;; @@ Quoted-Printable encode/decode string
75 (defun quoted-printable-encode-string (str)
82 ((or (< chr 32) (< 126 chr) (eq chr ?=))
86 (concat "=\n" (quoted-printable-quote-char chr))
90 (quoted-printable-quote-char chr)
95 (concat "=\n" (char-to-string chr))
104 (defun quoted-printable-decode-string (str)
112 (cond ((<= ?a chr) (+ (- chr ?a) 10))
113 ((<= ?A chr) (+ (- chr ?A) 10))
114 ((<= ?0 chr) (- chr ?0))
118 (h (setq l (cond ((<= ?a chr) (+ (- chr ?a) 10))
119 ((<= ?A chr) (+ (- chr ?A) 10))
120 ((<= ?0 chr) (- chr ?0))
123 (char-to-string (logior (ash h 4) l))
127 (t (char-to-string chr))
132 ;;; @@ Quoted-Printable encode/decode region
135 (defun quoted-printable-internal-encode-region (beg end)
138 (narrow-to-region beg end)
139 (let ((str (buffer-substring beg end)))
140 (delete-region beg end)
141 (insert (quoted-printable-encode-string str))
148 (defun quoted-printable-internal-decode-region (beg end)
151 (narrow-to-region beg end)
152 (goto-char (point-min))
153 (while (re-search-forward "=\n" nil t)
156 (goto-char (point-min))
158 (while (re-search-forward quoted-printable-octet-regexp nil t)
159 (setq b (match-beginning 0))
160 (setq e (match-end 0))
161 (setq str (buffer-substring b e))
163 (insert (quoted-printable-decode-string str))
167 (cond ((boundp 'MULE)
168 (define-program-coding-system
169 nil (car quoted-printable-external-encoder) *noconv*)
170 (define-program-coding-system
171 nil (car quoted-printable-external-decoder) *noconv*)
174 (define-program-kanji-code
175 nil (car quoted-printable-external-encoder) 0)
176 (define-program-kanji-code
177 nil (car quoted-printable-external-decoder) 0)
180 (defun quoted-printable-external-encode-region (beg end)
183 (narrow-to-region beg end)
184 (let ((selective-display nil) ;Disable ^M to nl translation.
186 (kanji-flag nil)) ;NEmacs
187 (apply (function call-process-region)
188 beg end (car quoted-printable-external-encoder)
189 t t nil (cdr quoted-printable-external-encoder))
192 ;; regularize line break code
193 (goto-char (point-min))
194 (while (re-search-forward "\r$" nil t)
199 (defun quoted-printable-external-decode-region (beg end)
201 (let ((selective-display nil) ;Disable ^M to nl translation.
203 (kanji-flag nil)) ;NEmacs
204 (apply (function call-process-region)
205 beg end (car quoted-printable-external-decoder)
206 t t nil (cdr quoted-printable-external-decoder))
209 (defun quoted-printable-encode-region (beg end)
211 (if (and quoted-printable-internal-encoding-limit
212 (> (- end beg) quoted-printable-internal-encoding-limit))
213 (quoted-printable-external-encode-region beg end)
214 (quoted-printable-internal-encode-region beg end)
217 (defun quoted-printable-decode-region (beg end)
219 (if (and quoted-printable-internal-decoding-limit
220 (> (- end beg) quoted-printable-internal-decoding-limit))
221 (quoted-printable-external-decode-region beg end)
222 (quoted-printable-internal-decode-region beg end)
226 ;;; @ Q-encoding encode/decode string
229 (defun q-encoding-encode-string-for-text (str)
232 (cond ((eq chr 32) "_")
233 ((or (< chr 32) (< 126 chr) (eq chr ?=))
234 (quoted-printable-quote-char chr)
236 (t (char-to-string chr))
240 (defun q-encoding-encode-string-for-comment (str)
243 (cond ((eq chr 32) "_")
244 ((or (< chr 32) (< 126 chr)
245 (memq chr '(?= ?\( ?\) ?\\))
247 (quoted-printable-quote-char chr)
249 (t (char-to-string chr))
253 (defun q-encoding-encode-string-for-phrase (str)
256 (cond ((eq chr 32) "_")
257 ((or (and (<= ?A chr)(<= chr ?Z))
258 (and (<= ?a chr)(<= chr ?z))
259 (and (<= ?0 chr)(<= chr ?9))
260 (memq chr '(?! ?* ?+ ?- ?/))
264 (t (quoted-printable-quote-char chr))
268 (defun q-encoding-encode-string (str &optional mode)
269 (cond ((eq mode 'text)
270 (q-encoding-encode-string-for-text str)
273 (q-encoding-encode-string-for-comment str)
276 (q-encoding-encode-string-for-phrase str)
279 (defun q-encoding-decode-string (str)
283 (cond ((eq chr ?_) " ")
287 (q (setq h (cond ((<= ?a chr) (+ (- chr ?a) 10))
288 ((<= ?A chr) (+ (- chr ?A) 10))
289 ((<= ?0 chr) (- chr ?0))
293 (h (setq l (cond ((<= ?a chr) (+ (- chr ?a) 10))
294 ((<= ?A chr) (+ (- chr ?A) 10))
295 ((<= ?0 chr) (- chr ?0))
298 (char-to-string (logior (ash h 4) l))
302 (t (char-to-string chr))
310 (defun q-encoding-encoded-length (string &optional mode)
311 (let ((l 0)(i 0)(len (length string)) chr)
313 (setq chr (elt string i))
314 (if (string-match "[A-Za-z0-9!*+/=_---]" (char-to-string chr))