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.2 1996/03/11 14:29:31 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.
35 (defconst quoted-printable-hex-chars "0123456789ABCDEF")
36 (defconst quoted-printable-octet-regexp
37 (concat "=[" quoted-printable-hex-chars
38 "][" quoted-printable-hex-chars "]"))
44 (defvar quoted-printable-external-encoder '("mmencode" "-q")
45 "*list of quoted-printable encoder program name and its arguments.")
47 (defvar quoted-printable-external-decoder '("mmencode" "-q" "-u")
48 "*list of quoted-printable decoder program name and its arguments.")
50 (defvar quoted-printable-internal-encoding-limit 10000
51 "*limit size to use internal quoted-printable encoder.
52 If size of input to encode is larger than this limit,
53 external encoder is called.")
55 (defvar quoted-printable-internal-decoding-limit nil
56 "*limit size to use internal quoted-printable decoder.
57 If size of input to decode is larger than this limit,
58 external decoder is called.")
61 ;;; @ Quoted-Printable (Q-encode) encoder/decoder
64 (defun byte-to-hex-string (num)
65 (concat (char-to-string (elt quoted-printable-hex-chars (ash num -4)))
66 (char-to-string (elt quoted-printable-hex-chars (logand num 15)))
69 (defun quoted-printable-quote-char (chr)
71 (char-to-string (elt quoted-printable-hex-chars (ash chr -4)))
72 (char-to-string (elt quoted-printable-hex-chars (logand chr 15)))
76 ;;; @@ Quoted-Printable encode/decode string
79 (defun quoted-printable-encode-string (str)
86 ((or (< chr 32) (< 126 chr) (eq chr ?=))
90 (concat "=\n" (quoted-printable-quote-char chr))
94 (quoted-printable-quote-char chr)
99 (concat "=\n" (char-to-string chr))
108 (defun quoted-printable-decode-string (str)
116 (cond ((<= ?a chr) (+ (- chr ?a) 10))
117 ((<= ?A chr) (+ (- chr ?A) 10))
118 ((<= ?0 chr) (- chr ?0))
122 (h (setq l (cond ((<= ?a chr) (+ (- chr ?a) 10))
123 ((<= ?A chr) (+ (- chr ?A) 10))
124 ((<= ?0 chr) (- chr ?0))
127 (char-to-string (logior (ash h 4) l))
131 (t (char-to-string chr))
136 ;;; @@ Quoted-Printable encode/decode region
139 (defun quoted-printable-internal-encode-region (beg end)
142 (narrow-to-region beg end)
143 (let ((str (buffer-substring beg end)))
144 (delete-region beg end)
145 (insert (quoted-printable-encode-string str))
152 (defun quoted-printable-internal-decode-region (beg end)
155 (narrow-to-region beg end)
156 (goto-char (point-min))
157 (while (re-search-forward "=\n" nil t)
160 (goto-char (point-min))
162 (while (re-search-forward quoted-printable-octet-regexp nil t)
163 (setq b (match-beginning 0))
164 (setq e (match-end 0))
165 (setq str (buffer-substring b e))
167 (insert (quoted-printable-decode-string str))
171 (cond ((boundp 'MULE)
172 (define-program-coding-system
173 nil (car quoted-printable-external-encoder) *noconv*)
174 (define-program-coding-system
175 nil (car quoted-printable-external-decoder) *noconv*)
178 (define-program-kanji-code
179 nil (car quoted-printable-external-encoder) 0)
180 (define-program-kanji-code
181 nil (car quoted-printable-external-decoder) 0)
184 (defun quoted-printable-external-encode-region (beg end)
187 (narrow-to-region beg end)
188 (let ((selective-display nil) ;Disable ^M to nl translation.
190 (kanji-flag nil)) ;NEmacs
191 (apply (function call-process-region)
192 beg end (car quoted-printable-external-encoder)
193 t t nil (cdr quoted-printable-external-encoder))
196 ;; regularize line break code
197 (goto-char (point-min))
198 (while (re-search-forward "\r$" nil t)
203 (defun quoted-printable-external-decode-region (beg end)
205 (let ((selective-display nil) ;Disable ^M to nl translation.
207 (kanji-flag nil)) ;NEmacs
208 (apply (function call-process-region)
209 beg end (car quoted-printable-external-decoder)
210 t t nil (cdr quoted-printable-external-decoder))
213 (defun quoted-printable-encode-region (beg end)
215 (if (and quoted-printable-internal-encoding-limit
216 (> (- end beg) quoted-printable-internal-encoding-limit))
217 (quoted-printable-external-encode-region beg end)
218 (quoted-printable-internal-encode-region beg end)
221 (defun quoted-printable-decode-region (beg end)
223 (if (and quoted-printable-internal-decoding-limit
224 (> (- end beg) quoted-printable-internal-decoding-limit))
225 (quoted-printable-external-decode-region beg end)
226 (quoted-printable-internal-decode-region beg end)
230 ;;; @ Q-encoding encode/decode string
233 (defun q-encoding-encode-string-for-text (str)
236 (cond ((eq chr 32) "_")
237 ((or (< chr 32) (< 126 chr) (eq chr ?=))
238 (quoted-printable-quote-char chr)
240 (t (char-to-string chr))
244 (defun q-encoding-encode-string-for-comment (str)
247 (cond ((eq chr 32) "_")
248 ((or (< chr 32) (< 126 chr)
249 (memq chr '(?= ?\( ?\) ?\\))
251 (quoted-printable-quote-char chr)
253 (t (char-to-string chr))
257 (defun q-encoding-encode-string-for-phrase (str)
260 (cond ((eq chr 32) "_")
261 ((or (and (<= ?A chr)(<= chr ?Z))
262 (and (<= ?a chr)(<= chr ?z))
263 (and (<= ?0 chr)(<= chr ?9))
264 (memq chr '(?! ?* ?+ ?- ?/))
268 (t (quoted-printable-quote-char chr))
272 (defun q-encoding-encode-string (str &optional mode)
273 (cond ((eq mode 'text)
274 (q-encoding-encode-string-for-text str)
277 (q-encoding-encode-string-for-comment str)
280 (q-encoding-encode-string-for-phrase str)
283 (defun q-encoding-decode-string (str)
287 (cond ((eq chr ?_) " ")
291 (q (setq h (cond ((<= ?a chr) (+ (- chr ?a) 10))
292 ((<= ?A chr) (+ (- chr ?A) 10))
293 ((<= ?0 chr) (- chr ?0))
297 (h (setq l (cond ((<= ?a chr) (+ (- chr ?a) 10))
298 ((<= ?A chr) (+ (- chr ?A) 10))
299 ((<= ?0 chr) (- chr ?0))
302 (char-to-string (logior (ash h 4) l))
306 (t (char-to-string chr))
314 (defun q-encoding-encoded-length (string &optional mode)
315 (let ((l 0)(i 0)(len (length string)) chr)
317 (setq chr (elt string i))
318 (if (string-match "[A-Za-z0-9!*+/=_---]" (char-to-string chr))
331 ;;; mel-q.el ends here