X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mel-q.el;h=63d95fb01e5785df993efad6d5c601ad8fb461cd;hb=b50be9fd88d89941795c5b5370e1ff667e617e59;hp=65390335ae7f363bb2900ac03ba23fb679ed6348;hpb=217869a91e7513b8bc5192f8994e2e710e0a0021;p=elisp%2Fflim.git diff --git a/mel-q.el b/mel-q.el index 6539033..63d95fb 100644 --- a/mel-q.el +++ b/mel-q.el @@ -1,76 +1,167 @@ -;;; -;;; $Id: mel-q.el,v 2.0 1995/09/11 11:33:47 morioka Exp $ -;;; +;;; mel-q.el: Quoted-Printable and Q-encoding encoder/decoder for GNU Emacs + +;; Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc. + +;; Author: MORIOKA Tomohiko +;; Created: 1995/6/25 +;; Keywords: MIME, Quoted-Printable, Q-encoding + +;; This file is part of MEL (MIME Encoding Library). + +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation; either version 2, or (at +;; your option) any later version. + +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Code: + +(require 'emu) + -;;; @ constants +;;; @ Quoted-Printable encoder ;;; (defconst quoted-printable-hex-chars "0123456789ABCDEF") -(defconst quoted-printable-octet-regexp - (concat "=[" quoted-printable-hex-chars - "][" quoted-printable-hex-chars "]")) +(defsubst quoted-printable-quote-char (character) + (concat + "=" + (char-to-string (aref quoted-printable-hex-chars (ash character -4))) + (char-to-string (aref quoted-printable-hex-chars (logand character 15))) + )) + +(defun quoted-printable-internal-encode-region (start end) + (save-excursion + (save-restriction + (narrow-to-region start end) + (goto-char start) + (let ((col 0) + enable-multibyte-characters) + (while (< (point)(point-max)) + (cond ((>= col 75) + (insert "=\n") + (setq col 0) + ) + ((looking-at "^From ") + (replace-match "=46rom ") + (backward-char 1) + (setq col (+ col 6)) + ) + ((looking-at "[ \t]\n") + (forward-char 1) + (insert "=\n") + (forward-char 1) + (setq col 0) + ) + (t + (let ((chr (char-after (point)))) + (cond ((= chr ?\n) + (forward-char 1) + (setq col 0) + ) + ((or (= chr ?\t) + (and (<= 32 chr)(/= chr ?=)(< chr 127)) + ) + (forward-char 1) + (setq col (1+ col)) + ) + ((>= col 73) + (insert "=\n") + (setq col 0) + ) + (t + (delete-char 1) + (insert (quoted-printable-quote-char chr)) + (setq col (+ col 3)) + )) + ))) + ))))) -;;; @ variables -;;; (defvar quoted-printable-external-encoder '("mmencode" "-q") "*list of quoted-printable encoder program name and its arguments.") -(defvar quoted-printable-external-decoder '("mmencode" "-q" "-u") - "*list of quoted-printable decoder program name and its arguments.") +(defun quoted-printable-external-encode-region (start end) + (save-excursion + (save-restriction + (narrow-to-region start end) + (as-binary-process + (apply (function call-process-region) + start end (car quoted-printable-external-encoder) + t t nil (cdr quoted-printable-external-encoder)) + ) + ;; for OS/2 + ;; regularize line break code + (goto-char (point-min)) + (while (re-search-forward "\r$" nil t) + (replace-match "") + ) + ))) -(defvar quoted-printable-internal-encoding-limit 10000 + +(defvar quoted-printable-internal-encoding-limit + (if (and (featurep 'xemacs)(featurep 'mule)) + 0 + (require 'path-util) + (if (exec-installed-p "mmencode") + 1000 + (message "Don't found external encoder for Quoted-Printable!") + nil)) "*limit size to use internal quoted-printable encoder. If size of input to encode is larger than this limit, external encoder is called.") -(defvar quoted-printable-internal-decoding-limit nil - "*limit size to use internal quoted-printable decoder. -If size of input to decode is larger than this limit, -external decoder is called.") +(defun quoted-printable-encode-region (start end) + "Encode current region by quoted-printable. +START and END are buffer positions. +This function calls internal quoted-printable encoder if size of +region is smaller than `quoted-printable-internal-encoding-limit', +otherwise it calls external quoted-printable encoder specified by +`quoted-printable-external-encoder'. In this case, you must install +the program (maybe mmencode included in metamail or XEmacs package)." + (interactive "r") + (if (and quoted-printable-internal-encoding-limit + (> (- end start) quoted-printable-internal-encoding-limit)) + (quoted-printable-external-encode-region start end) + (quoted-printable-internal-encode-region start end) + )) -;;; @ Quoted-Printable (Q-encode) encoder/decoder -;;; +(defun quoted-printable-encode-string (string) + "Encode STRING to quoted-printable, and return the result." + (with-temp-buffer + (insert string) + (quoted-printable-encode-region (point-min)(point-max)) + (buffer-string) + )) -(defun quoted-printable-quote-char (chr) - (concat "=" - (char-to-string (elt quoted-printable-hex-chars (ash chr -4))) - (char-to-string (elt quoted-printable-hex-chars (logand chr 15))) - )) +(defun quoted-printable-insert-encoded-file (filename) + "Encode contents of file FILENAME to quoted-printable, and insert the result. +It calls external quoted-printable encoder specified by +`quoted-printable-external-encoder'. So you must install the program +\(maybe mmencode included in metamail or XEmacs package)." + (interactive (list (read-file-name "Insert encoded file: "))) + (apply (function call-process) (car quoted-printable-external-encoder) + filename t nil (cdr quoted-printable-external-encoder)) + ) -;;; @@ Quoted-Printable encode/decode string -;;; -(defun quoted-printable-encode-string (str) - (let ((i 0)) - (mapconcat (function - (lambda (chr) - (cond ((or (< chr 32) (< 126 chr) (eq chr ?=)) - (if (>= i 73) - (progn - (setq i 0) - (concat "=\n" (quoted-printable-quote-char chr)) - ) - (progn - (setq i (+ i 3)) - (quoted-printable-quote-char chr) - ))) - (t (if (>= i 75) - (progn - (setq i 0) - (concat "=\n" (char-to-string chr)) - ) - (progn - (setq i (1+ i)) - (char-to-string chr) - ))) - ))) - str ""))) +;;; @ Quoted-Printable decoder +;;; -(defun quoted-printable-decode-string (str) +(defun quoted-printable-decode-string (string) + "Decode STRING which is encoded in quoted-printable, and return the result." (let (q h l) (mapconcat (function (lambda (chr) @@ -95,39 +186,16 @@ external decoder is called.") ) (t (char-to-string chr)) ))) - str ""))) - - -;;; @@ Quoted-Printable encode/decode region -;;; + string ""))) -(defun quoted-printable-internal-encode-region (beg end) - (save-excursion - (save-restriction - (narrow-to-region beg end) - (goto-char (point-min)) - (catch 'tag - (let (b e str) - (while t - (beginning-of-line) (setq b (point)) - (end-of-line) (setq e (point)) - (if (< b e) - (progn - (setq str (buffer-substring b e)) - (delete-region b e) - (insert (quoted-printable-encode-string str)) - )) - (if (eobp) - (throw 'tag nil) - ) - (forward-char 1) - ))) - ))) +(defconst quoted-printable-octet-regexp + (concat "=[" quoted-printable-hex-chars + "][" quoted-printable-hex-chars "]")) -(defun quoted-printable-internal-decode-region (beg end) +(defun quoted-printable-internal-decode-region (start end) (save-excursion (save-restriction - (narrow-to-region beg end) + (narrow-to-region start end) (goto-char (point-min)) (while (re-search-forward "=\n" nil t) (replace-match "") @@ -143,104 +211,93 @@ external decoder is called.") )) ))) -(cond ((boundp 'MULE) - (define-program-coding-system - nil (car quoted-printable-external-encoder) *noconv*) - (define-program-coding-system - nil (car quoted-printable-external-decoder) *noconv*) - ) - ((boundp 'NEMACS) - (define-program-kanji-code - nil (car quoted-printable-external-encoder) 0) - (define-program-kanji-code - nil (car quoted-printable-external-decoder) 0) - )) - -(defun quoted-printable-external-encode-region (beg end) - (save-excursion - (apply (function call-process-region) - beg end (car quoted-printable-external-encoder) - t t nil (cdr quoted-printable-external-encoder)) - )) -(defun quoted-printable-external-decode-region (beg end) +(defvar quoted-printable-external-decoder '("mmencode" "-q" "-u") + "*list of quoted-printable decoder program name and its arguments.") + +(defun quoted-printable-external-decode-region (start end) (save-excursion - (apply (function call-process-region) - beg end (car quoted-printable-external-decoder) - t t nil (cdr quoted-printable-external-decoder)) - )) + (as-binary-process + (apply (function call-process-region) + start end (car quoted-printable-external-decoder) + t t nil (cdr quoted-printable-external-decoder)) + ))) -(defun quoted-printable-encode-region (beg end) - (interactive "r") - (if (and quoted-printable-internal-encoding-limit - (> (- end beg) quoted-printable-internal-encoding-limit)) - (quoted-printable-external-encode-region beg end) - (quoted-printable-internal-encode-region beg end) - )) -(defun quoted-printable-decode-region (beg end) +(defvar quoted-printable-internal-decoding-limit nil + "*limit size to use internal quoted-printable decoder. +If size of input to decode is larger than this limit, +external decoder is called.") + +(defun quoted-printable-decode-region (start end) + "Decode current region by quoted-printable. +START and END are buffer positions. +This function calls internal quoted-printable decoder if size of +region is smaller than `quoted-printable-internal-decoding-limit', +otherwise it calls external quoted-printable decoder specified by +`quoted-printable-external-decoder'. In this case, you must install +the program (maybe mmencode included in metamail or XEmacs package)." (interactive "r") (if (and quoted-printable-internal-decoding-limit - (> (- end beg) quoted-printable-internal-decoding-limit)) - (quoted-printable-external-decode-region beg end) - (quoted-printable-internal-decode-region beg end) + (> (- end start) quoted-printable-internal-decoding-limit)) + (quoted-printable-external-decode-region start end) + (quoted-printable-internal-decode-region start end) )) +(defvar quoted-printable-external-decoder-option-to-specify-file '("-o") + "*list of options of quoted-printable decoder program to specify file.") + +(defun quoted-printable-write-decoded-region (start end filename) + "Decode and write current region encoded by quoted-printable into FILENAME. +START and END are buffer positions." + (interactive + (list (region-beginning) (region-end) + (read-file-name "Write decoded region to file: "))) + (as-binary-process + (apply (function call-process-region) + start end (car quoted-printable-external-decoder) + nil nil nil + (append (cdr quoted-printable-external-decoder) + quoted-printable-external-decoder-option-to-specify-file + (list filename)) + ))) + + ;;; @ Q-encoding encode/decode string ;;; -(defun q-encoding-encode-string-for-text (str) - (mapconcat (function - (lambda (chr) - (cond ((eq chr 32) "_") - ((or (< chr 32) (< 126 chr) (eq chr ?=)) - (quoted-printable-quote-char chr) - ) - (t (char-to-string chr)) - ))) - str "")) - -(defun q-encoding-encode-string-for-comment (str) - (mapconcat (function - (lambda (chr) - (cond ((eq chr 32) "_") - ((or (< chr 32) (< 126 chr) - (memq chr '(?= ?\( ?\) ?\\)) - ) - (quoted-printable-quote-char chr) - ) - (t (char-to-string chr)) - ))) - str "")) - -(defun q-encoding-encode-string-for-phrase (str) - (mapconcat (function - (lambda (chr) - (cond ((eq chr 32) "_") - ((or (and (<= ?A chr)(<= chr ?Z)) - (and (<= ?a chr)(<= chr ?z)) - (and (<= ?0 chr)(<= chr ?9)) - (memq chr '(?! ?* ?+ ?- ?/)) - ) - (char-to-string chr) - ) - (t (quoted-printable-quote-char chr)) - ))) - str "")) - -(defun q-encoding-encode-string (str &optional mode) - (cond ((eq mode 'text) - (q-encoding-encode-string-for-text str) - ) - ((eq mode 'comment) - (q-encoding-encode-string-for-comment str) - ) - (t - (q-encoding-encode-string-for-phrase str) - ))) - -(defun q-encoding-decode-string (str) +(defconst q-encoding-special-chars-alist + '((text ?= ?? ?_) + (comment ?= ?? ?_ ?\( ?\) ?\\) + (phrase ?= ?? ?_ ?\( ?\) ?\\ ?\" ?# ?$ ?% ?& ?' ?, ?. ?/ + ?: ?\; ?< ?> ?@ ?\[ ?\] ?^ ?` ?{ ?| ?} ?~) + )) + +(defun q-encoding-encode-string (string &optional mode) + "Encode STRING to Q-encoding of encoded-word, and return the result. +MODE allows `text', `comment', `phrase' or nil. Default value is +`phrase'." + (let ((specials (cdr (or (assq mode q-encoding-special-chars-alist) + (assq 'phrase q-encoding-special-chars-alist) + )))) + (mapconcat (function + (lambda (chr) + (cond ((eq chr ? ) "_") + ((or (< chr 32) (< 126 chr) + (memq chr specials) + ) + (quoted-printable-quote-char chr) + ) + (t + (char-to-string chr) + )) + )) + string "") + )) + +(defun q-encoding-decode-string (string) + "Decode STRING which is encoded in Q-encoding and return the result." (let (q h l) (mapconcat (function (lambda (chr) @@ -265,17 +322,28 @@ external decoder is called.") ) (t (char-to-string chr)) ))) - str ""))) + string ""))) ;;; @@ etc ;;; +(defun q-encoding-printable-char-p (chr mode) + (and (not (memq chr '(?= ?? ?_))) + (<= ?\ chr)(<= chr ?~) + (cond ((eq mode 'text) t) + ((eq mode 'comment) + (not (memq chr '(?\( ?\) ?\\))) + ) + (t + (string-match "[A-Za-z0-9!*+/=_---]" (char-to-string chr)) + )))) + (defun q-encoding-encoded-length (string &optional mode) (let ((l 0)(i 0)(len (length string)) chr) (while (< i len) (setq chr (elt string i)) - (if (string-match "[A-Za-z0-9!*+/=_---]" (char-to-string chr)) + (if (q-encoding-printable-char-p chr mode) (setq l (+ l 1)) (setq l (+ l 3)) ) @@ -287,3 +355,5 @@ external decoder is called.") ;;; (provide 'mel-q) + +;;; mel-q.el ends here