Mercurial > hg > xemacs-beta
comparison lisp/tm/tm-edit.el @ 4:b82b59fe008d r19-15b3
Import from CVS: tag r19-15b3
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:46:56 +0200 |
parents | |
children | 4b173ad71786 |
comparison
equal
deleted
inserted
replaced
3:30df88044ec6 | 4:b82b59fe008d |
---|---|
1 ;;; tm-edit.el --- Simple MIME Composer for GNU Emacs | |
2 | |
3 ;; Copyright (C) 1993 .. 1996 Free Software Foundation, Inc. | |
4 | |
5 ;; Author: UMEDA Masanobu <umerin@mse.kyutech.ac.jp> | |
6 ;; MORIOKA Tomohiko <morioka@jaist.ac.jp> | |
7 ;; Maintainer: MORIOKA Tomohiko <morioka@jaist.ac.jp> | |
8 ;; Created: 1994/08/21 renamed from mime.el | |
9 ;; Version: $Revision: 1.1.1.1 $ | |
10 ;; Keywords: mail, news, MIME, multimedia, multilingual | |
11 | |
12 ;; This file is part of tm (Tools for MIME). | |
13 | |
14 ;; This program is free software; you can redistribute it and/or | |
15 ;; modify it under the terms of the GNU General Public License as | |
16 ;; published by the Free Software Foundation; either version 2, or (at | |
17 ;; your option) any later version. | |
18 | |
19 ;; This program is distributed in the hope that it will be useful, but | |
20 ;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
22 ;; General Public License for more details. | |
23 | |
24 ;; You should have received a copy of the GNU General Public License | |
25 ;; along with GNU Emacs; see the file COPYING. If not, write to the | |
26 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
27 ;; Boston, MA 02111-1307, USA. | |
28 | |
29 ;;; Commentary: | |
30 | |
31 ;; This is an Emacs minor mode for editing Internet multimedia | |
32 ;; messages formatted in MIME (RFC 2045, 2046, 2047, 2048 and 2049). | |
33 ;; All messages in this mode are composed in the tagged MIME format, | |
34 ;; that are described in the following examples. The messages | |
35 ;; composed in the tagged MIME format are automatically translated | |
36 ;; into a MIME compliant message when exiting the mode. | |
37 | |
38 ;; Mule (a multilingual extension to Emacs 18 and 19) has a capability | |
39 ;; of handling multilingual text in limited ISO-2022 manner that is | |
40 ;; based on early experiences in Japanese Internet community and | |
41 ;; resulted in RFC 1468 (ISO-2022-JP charset for MIME). In order to | |
42 ;; enable multilingual capability in single text message in MIME, | |
43 ;; charset of multilingual text written in Mule is declared as either | |
44 ;; `ISO-2022-JP-2' [RFC 1554] or `ISO-2022-INT-1'. Mule is required | |
45 ;; for reading the such messages. | |
46 | |
47 ;; This MIME composer can work with Mail mode, mh-e letter Mode, and | |
48 ;; News mode. First of all, you need the following autoload | |
49 ;; definition to load mime/editor-mode automatically: | |
50 ;; | |
51 ;; (autoload 'mime/editor-mode "tm-edit" | |
52 ;; "Minor mode for editing MIME message." t) | |
53 ;; | |
54 ;; In case of Mail mode (includes VM mode), you need the following | |
55 ;; hook definition: | |
56 ;; | |
57 ;; (add-hook 'mail-mode-hook 'mime/editor-mode) | |
58 ;; (add-hook 'mail-send-hook 'mime-editor/maybe-translate) | |
59 ;; | |
60 ;; In case of MH-E, you need the following hook definition: | |
61 ;; | |
62 ;; (add-hook 'mh-letter-mode-hook | |
63 ;; (function | |
64 ;; (lambda () | |
65 ;; (mime/editor-mode) | |
66 ;; (make-local-variable 'mail-header-separator) | |
67 ;; (setq mail-header-separator "--------") | |
68 ;; )))) | |
69 ;; (add-hook 'mh-before-send-letter-hook 'mime-editor/maybe-translate) | |
70 ;; | |
71 ;; In case of News mode, you need the following hook definition: | |
72 ;; | |
73 ;; (add-hook 'news-reply-mode-hook 'mime/editor-mode) | |
74 ;; (add-hook 'news-inews-hook 'mime-editor/maybe-translate) | |
75 ;; | |
76 ;; In case of Emacs 19, it is possible to emphasize the message tags | |
77 ;; using font-lock mode as follows: | |
78 ;; | |
79 ;; (add-hook 'mime/editor-mode-hook | |
80 ;; (function | |
81 ;; (lambda () | |
82 ;; (font-lock-mode 1) | |
83 ;; (setq font-lock-keywords (list mime-editor/tag-regexp)) | |
84 ;; )))) | |
85 | |
86 ;; The message tag looks like: | |
87 ;; | |
88 ;; --[[TYPE/SUBTYPE;PARAMETERS][ENCODING]] | |
89 ;; | |
90 ;; The tagged MIME message examples: | |
91 ;; | |
92 ;; This is a conventional plain text. It should be translated into | |
93 ;; text/plain. | |
94 ;; | |
95 ;;--[[text/plain]] | |
96 ;; This is also a plain text. But, it is explicitly specified as is. | |
97 ;; | |
98 ;;--[[text/plain; charset=ISO-2022-JP]] | |
99 ;; これは charset を ISO-2022-JP に指定した日本語の plain テキストです. | |
100 ;; | |
101 ;;--[[text/richtext]] | |
102 ;; <center>This is a richtext.</center> | |
103 ;; | |
104 ;;--[[image/gif][base64]]^M...image encoded in base64 comes here... | |
105 ;; | |
106 ;;--[[audio/basic][base64]]^M...audio encoded in base64 comes here... | |
107 | |
108 ;;; Code: | |
109 | |
110 (require 'sendmail) | |
111 (require 'mail-utils) | |
112 (require 'mel) | |
113 (require 'tl-822) | |
114 (require 'tl-list) | |
115 (require 'tm-view) | |
116 (require 'tm-ew-e) | |
117 (require 'signature) | |
118 | |
119 | |
120 ;;; @ version | |
121 ;;; | |
122 | |
123 (defconst mime-editor/RCS-ID | |
124 "$Id: tm-edit.el,v 1.1.1.1 1996/12/18 03:55:31 steve Exp $") | |
125 | |
126 (defconst mime-editor/version (get-version-string mime-editor/RCS-ID)) | |
127 | |
128 (defconst mime-editor/version-name | |
129 (concat "tm-edit " mime-editor/version)) | |
130 | |
131 | |
132 ;;; @ variables | |
133 ;;; | |
134 | |
135 (defvar mime-prefix "\C-c\C-x" | |
136 "*Keymap prefix for MIME commands.") | |
137 | |
138 (defvar mime-ignore-preceding-spaces nil | |
139 "*Ignore preceding white spaces if non-nil.") | |
140 | |
141 (defvar mime-ignore-trailing-spaces nil | |
142 "*Ignore trailing white spaces if non-nil.") | |
143 | |
144 (defvar mime-ignore-same-text-tag t | |
145 "*Ignore preceding text content-type tag that is same with new one. | |
146 If non-nil, the text tag is not inserted unless something different.") | |
147 | |
148 (defvar mime-auto-hide-body t | |
149 "*Hide non-textual body encoded in base64 after insertion if non-nil.") | |
150 | |
151 (defvar mime-editor/voice-recorder | |
152 (function mime-editor/voice-recorder-for-sun) | |
153 "*Function to record a voice message and encode it. [tm-edit.el]") | |
154 | |
155 (defvar mime/editor-mode-hook nil | |
156 "*Hook called when enter MIME mode.") | |
157 | |
158 (defvar mime-editor/translate-hook nil | |
159 "*Hook called before translating into a MIME compliant message. | |
160 To insert a signature file automatically, call the function | |
161 `mime-editor/insert-signature' from this hook.") | |
162 | |
163 (defvar mime-editor/exit-hook nil | |
164 "*Hook called when exit MIME mode.") | |
165 | |
166 (defvar mime-content-types | |
167 '(("text" | |
168 ;; Charset parameter need not to be specified, since it is | |
169 ;; defined automatically while translation. | |
170 ("plain" | |
171 ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8") | |
172 ) | |
173 ("richtext" | |
174 ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8") | |
175 ) | |
176 ("enriched" | |
177 ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8") | |
178 ) | |
179 ("x-latex" | |
180 ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8") | |
181 ) | |
182 ("html" | |
183 ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8") | |
184 ) | |
185 ("x-rot13-47") | |
186 ) | |
187 ("message" | |
188 ("external-body" | |
189 ("access-type" | |
190 ("anon-ftp" | |
191 ("site" "ftp.jaist.ac.jp" "wnoc-fuk.wide.ad.jp" "nic.karrn.ad.jp") | |
192 ("directory" "/pub/GNU/elisp/mime") | |
193 ("name") | |
194 ("mode" "image" "ascii" "local8")) | |
195 ("ftp" | |
196 ("site") | |
197 ("directory") | |
198 ("name") | |
199 ("mode" "image" "ascii" "local8")) | |
200 ("tftp" ("site") ("name")) | |
201 ("afs" ("site") ("name")) | |
202 ("local-file" ("site") ("name")) | |
203 ("mail-server" ("server" "ftpmail@nic.karrn.ad.jp")) | |
204 )) | |
205 ("rfc822") | |
206 ) | |
207 ("application" | |
208 ("octet-stream" ("type" "" "tar" "shar")) | |
209 ("postscript") | |
210 ("x-kiss" ("x-cnf"))) | |
211 ("image" | |
212 ("gif") | |
213 ("jpeg") | |
214 ("tiff") | |
215 ("x-pic") | |
216 ("x-mag") | |
217 ("x-xwd") | |
218 ("x-xbm") | |
219 ) | |
220 ("audio" ("basic")) | |
221 ("video" ("mpeg")) | |
222 ) | |
223 "*Alist of content-type, subtype, parameters and its values.") | |
224 | |
225 (defvar mime-file-types | |
226 '(("\\.rtf$" | |
227 "text" "richtext" nil | |
228 nil | |
229 nil nil) | |
230 ("\\.html$" | |
231 "text" "html" nil | |
232 nil | |
233 nil nil) | |
234 ("\\.ps$" | |
235 "application" "postscript" nil | |
236 "quoted-printable" | |
237 "attachment" (("filename" . file)) | |
238 ) | |
239 ("\\.jpg$" | |
240 "image" "jpeg" nil | |
241 "base64" | |
242 "inline" (("filename" . file)) | |
243 ) | |
244 ("\\.gif$" | |
245 "image" "gif" nil | |
246 "base64" | |
247 "inline" (("filename" . file)) | |
248 ) | |
249 ("\\.tiff$" | |
250 "image" "tiff" nil | |
251 "base64" | |
252 "inline" (("filename" . file)) | |
253 ) | |
254 ("\\.pic$" | |
255 "image" "x-pic" nil | |
256 "base64" | |
257 "inline" (("filename" . file)) | |
258 ) | |
259 ("\\.mag$" | |
260 "image" "x-mag" nil | |
261 "base64" | |
262 "inline" (("filename" . file)) | |
263 ) | |
264 ("\\.xbm$" | |
265 "image" "x-xbm" nil | |
266 "base64" | |
267 "inline" (("filename" . file)) | |
268 ) | |
269 ("\\.xwd$" | |
270 "image" "x-xwd" nil | |
271 "base64" | |
272 "inline" (("filename" . file)) | |
273 ) | |
274 ("\\.au$" | |
275 "audio" "basic" nil | |
276 "base64" | |
277 "attachment" (("filename" . file)) | |
278 ) | |
279 ("\\.mpg$" | |
280 "video" "mpeg" nil | |
281 "base64" | |
282 "attachment" (("filename" . file)) | |
283 ) | |
284 ("\\.el$" | |
285 "application" "octet-stream" (("type" . "emacs-lisp")) | |
286 "7bit" | |
287 "attachment" (("filename" . file)) | |
288 ) | |
289 ("\\.lsp$" | |
290 "application" "octet-stream" (("type" . "common-lisp")) | |
291 "7bit" | |
292 "attachment" (("filename" . file)) | |
293 ) | |
294 ("\\.tar\\.gz$" | |
295 "application" "octet-stream" (("type" . "tar+gzip")) | |
296 nil | |
297 "attachment" (("filename" . file)) | |
298 ) | |
299 ("\\.tgz$" | |
300 "application" "octet-stream" (("type" . "tar+gzip")) | |
301 nil | |
302 "attachment" (("filename" . file)) | |
303 ) | |
304 ("\\.tar\\.Z$" | |
305 "application" "octet-stream" (("type" . "tar+compress")) | |
306 nil | |
307 "attachment" (("filename" . file)) | |
308 ) | |
309 ("\\.taz$" | |
310 "application" "octet-stream" (("type" . "tar+compress")) | |
311 nil | |
312 "attachment" (("filename" . file)) | |
313 ) | |
314 ("\\.gz$" | |
315 "application" "octet-stream" (("type" . "gzip")) | |
316 nil | |
317 "attachment" (("filename" . file)) | |
318 ) | |
319 ("\\.Z$" | |
320 "application" "octet-stream" (("type" . "compress")) | |
321 nil | |
322 "attachment" (("filename" . file)) | |
323 ) | |
324 ("\\.lzh$" | |
325 "application" "octet-stream" (("type" . "lha")) | |
326 nil | |
327 "attachment" (("filename" . file)) | |
328 ) | |
329 ("\\.zip$" | |
330 "application" "zip" nil | |
331 nil | |
332 "attachment" (("filename" . file)) | |
333 ) | |
334 ("\\.diff$" | |
335 "application" "octet-stream" (("type" . "patch")) | |
336 nil | |
337 "attachment" (("filename" . file)) | |
338 ) | |
339 ("\\.patch$" | |
340 "application" "octet-stream" (("type" . "patch")) | |
341 nil | |
342 "attachment" (("filename" . file)) | |
343 ) | |
344 ("\\.signature" | |
345 "text" "plain" nil nil) | |
346 (".*" | |
347 "application" "octet-stream" nil | |
348 nil | |
349 "attachment" (("filename" . file)) | |
350 ) | |
351 ) | |
352 "*Alist of file name, types, parameters, and default encoding. | |
353 If encoding is nil, it is determined from its contents.") | |
354 | |
355 ;;; @@ about charset, encoding and transfer-level | |
356 ;;; | |
357 | |
358 (defvar mime-editor/transfer-level 7 | |
359 "*A number of network transfer level. It should be bigger than 7.") | |
360 (make-variable-buffer-local 'mime-editor/transfer-level) | |
361 | |
362 (defvar mime-editor/transfer-level-string | |
363 (mime/encoding-name mime-editor/transfer-level 'not-omit) | |
364 "*A string formatted version of mime/defaul-transfer-level") | |
365 (make-variable-buffer-local 'mime-editor/transfer-level-string) | |
366 | |
367 (defun mime-editor/make-charset-default-encoding-alist (transfer-level) | |
368 (mapcar (function | |
369 (lambda (charset-type) | |
370 (let ((charset (car charset-type)) | |
371 (type (nth 1 charset-type)) | |
372 (encoding (nth 2 charset-type)) | |
373 ) | |
374 (if (<= type transfer-level) | |
375 (cons charset (mime/encoding-name type)) | |
376 (cons charset encoding) | |
377 )))) | |
378 mime-charset-type-list)) | |
379 | |
380 (defvar mime-editor/charset-default-encoding-alist | |
381 (mime-editor/make-charset-default-encoding-alist mime-editor/transfer-level)) | |
382 (make-variable-buffer-local 'mime-editor/charset-default-encoding-alist) | |
383 | |
384 ;;; @@ about message inserting | |
385 ;;; | |
386 | |
387 (defvar mime-editor/yank-ignored-field-list | |
388 '("Received" "Approved" "Path" "Replied" "Status" | |
389 "Xref" "X-UIDL" "X-Filter" "X-Gnus-.*" "X-VM-.*") | |
390 "Delete these fields from original message when it is inserted | |
391 as message/rfc822 part. | |
392 Each elements are regexp of field-name. [tm-edit.el]") | |
393 | |
394 (defvar mime-editor/yank-ignored-field-regexp | |
395 (concat "^" | |
396 (apply (function regexp-or) mime-editor/yank-ignored-field-list) | |
397 ":")) | |
398 | |
399 (defvar mime-editor/message-inserter-alist nil) | |
400 (defvar mime-editor/mail-inserter-alist nil) | |
401 | |
402 ;;; @@ about message splitting | |
403 ;;; | |
404 | |
405 (defvar mime-editor/split-message t | |
406 "*Split large message if it is non-nil. [tm-edit.el]") | |
407 | |
408 (defvar mime-editor/message-default-max-lines 1000 | |
409 "*Default maximum lines of a message. [tm-edit.el]") | |
410 | |
411 (defvar mime-editor/message-max-lines-alist | |
412 '((news-reply-mode . 500)) | |
413 "Alist of major-mode vs maximum lines of a message. | |
414 If it is not specified for a major-mode, | |
415 `mime-editor/message-default-max-lines' is used. [tm-edit.el]") | |
416 | |
417 (defconst mime-editor/split-ignored-field-regexp | |
418 "\\(^Content-\\|^Subject:\\|^Mime-Version:\\)") | |
419 | |
420 (defvar mime-editor/split-blind-field-regexp | |
421 "\\(^[BDFbdf]cc:\\|^cc:[ \t]*$\\)") | |
422 | |
423 (defvar mime-editor/split-message-sender-alist nil) | |
424 | |
425 (defvar mime-editor/news-reply-mode-server-running nil) | |
426 | |
427 | |
428 ;;; @@ about PGP | |
429 ;;; | |
430 | |
431 (defvar mime-editor/signing-type 'pgp-elkins | |
432 "*PGP signing type (pgp-elkins, pgp-kazu or nil). [tm-edit.el]") | |
433 | |
434 (defvar mime-editor/encrypting-type 'pgp-elkins | |
435 "*PGP encrypting type (pgp-elkins, pgp-kazu or nil). [tm-edit.el]") | |
436 | |
437 (defvar mime-editor/pgp-sign-function 'tm:mc-pgp-sign-region) | |
438 (defvar mime-editor/pgp-encrypt-function 'tm:mc-pgp-encrypt-region) | |
439 (defvar mime-editor/traditional-pgp-sign-function 'mc-pgp-sign-region) | |
440 (defvar mime-editor/pgp-insert-public-key-function 'mc-insert-public-key) | |
441 | |
442 (autoload mime-editor/pgp-sign-function "tm-edit-mc") | |
443 (autoload mime-editor/pgp-encrypt-function "tm-edit-mc") | |
444 (autoload mime-editor/traditional-pgp-sign-function "mc-pgp") | |
445 (autoload mime-editor/pgp-insert-public-key-function "mc-toplev") | |
446 | |
447 | |
448 ;;; @@ about tag | |
449 ;;; | |
450 | |
451 (defconst mime-editor/single-part-tag-regexp | |
452 "--[[][[]\\([^]]*\\)]\\([[]\\([^]]*\\)]\\|\\)]" | |
453 "*Regexp of MIME tag in the form of [[CONTENT-TYPE][ENCODING]].") | |
454 | |
455 (defconst mime-editor/quoted-single-part-tag-regexp | |
456 (concat "- " (substring mime-editor/single-part-tag-regexp 1))) | |
457 | |
458 (defconst mime-editor/multipart-beginning-regexp "--<<\\([^<>]+\\)>>-{\n") | |
459 | |
460 (defconst mime-editor/multipart-end-regexp "--}-<<\\([^<>]+\\)>>\n") | |
461 | |
462 (defconst mime-editor/beginning-tag-regexp | |
463 (regexp-or mime-editor/single-part-tag-regexp | |
464 mime-editor/multipart-beginning-regexp)) | |
465 | |
466 (defconst mime-editor/end-tag-regexp | |
467 (regexp-or mime-editor/single-part-tag-regexp | |
468 mime-editor/multipart-end-regexp)) | |
469 | |
470 (defconst mime-editor/tag-regexp | |
471 (regexp-or mime-editor/single-part-tag-regexp | |
472 mime-editor/multipart-beginning-regexp | |
473 mime-editor/multipart-end-regexp)) | |
474 | |
475 (defvar mime-tag-format "--[[%s]]" | |
476 "*Control-string making a MIME tag.") | |
477 | |
478 (defvar mime-tag-format-with-encoding "--[[%s][%s]]" | |
479 "*Control-string making a MIME tag with encoding.") | |
480 | |
481 ;;; @@ multipart boundary | |
482 ;;; | |
483 | |
484 (defvar mime-multipart-boundary "Multipart" | |
485 "*Boundary of a multipart message.") | |
486 | |
487 | |
488 ;;; @@ buffer local variables | |
489 ;;; | |
490 | |
491 (defvar mime/editor-mode-old-local-map nil) | |
492 (defvar mime/editing-buffer nil) | |
493 | |
494 | |
495 ;;; @ constants | |
496 ;;; | |
497 | |
498 (defconst mime-tspecials-regexp "[][()<>@,;:\\\"/?.= \t]" | |
499 "*Specify MIME tspecials. | |
500 Tspecials means any character that matches with it in header must be quoted.") | |
501 | |
502 (defconst mime-editor/mime-version-value | |
503 (concat "1.0 (generated by " mime-editor/version-name ")") | |
504 "MIME version number.") | |
505 | |
506 (defconst mime-editor/mime-map (make-sparse-keymap) | |
507 "Keymap for MIME commands.") | |
508 | |
509 ;;; @ keymap and menu | |
510 ;;; | |
511 | |
512 (defvar mime/editor-mode-flag nil) | |
513 (make-variable-buffer-local 'mime/editor-mode-flag) | |
514 | |
515 (defun mime-editor/define-keymap (keymap) | |
516 "Add mime-editor commands to KEYMAP." | |
517 (if (not (keymapp keymap)) | |
518 nil | |
519 (define-key keymap "\C-t" 'mime-editor/insert-text) | |
520 (define-key keymap "\C-i" 'mime-editor/insert-file) | |
521 (define-key keymap "\C-e" 'mime-editor/insert-external) | |
522 (define-key keymap "\C-v" 'mime-editor/insert-voice) | |
523 (define-key keymap "\C-y" 'mime-editor/insert-message) | |
524 (define-key keymap "\C-m" 'mime-editor/insert-mail) | |
525 (define-key keymap "\C-w" 'mime-editor/insert-signature) | |
526 (define-key keymap "\C-s" 'mime-editor/insert-signature) | |
527 (define-key keymap "\C-k" 'mime-editor/insert-key) | |
528 (define-key keymap "t" 'mime-editor/insert-tag) | |
529 (define-key keymap "a" 'mime-editor/enclose-alternative-region) | |
530 (define-key keymap "p" 'mime-editor/enclose-parallel-region) | |
531 (define-key keymap "m" 'mime-editor/enclose-mixed-region) | |
532 (define-key keymap "d" 'mime-editor/enclose-digest-region) | |
533 (define-key keymap "s" 'mime-editor/enclose-signed-region) | |
534 (define-key keymap "e" 'mime-editor/enclose-encrypted-region) | |
535 (define-key keymap "q" 'mime-editor/enclose-quote-region) | |
536 (define-key keymap "7" 'mime-editor/set-transfer-level-7bit) | |
537 (define-key keymap "8" 'mime-editor/set-transfer-level-8bit) | |
538 (define-key keymap "/" 'mime-editor/set-split) | |
539 (define-key keymap "v" 'mime-editor/set-sign) | |
540 (define-key keymap "h" 'mime-editor/set-encrypt) | |
541 (define-key keymap "\C-p" 'mime-editor/preview-message) | |
542 (define-key keymap "\C-z" 'mime-editor/exit) | |
543 (define-key keymap "?" 'mime-editor/help) | |
544 )) | |
545 | |
546 (mime-editor/define-keymap mime-editor/mime-map) | |
547 | |
548 (defun mime-editor/toggle-mode () | |
549 (interactive) | |
550 (if mime/editor-mode-flag | |
551 (mime-editor/exit 'nomime) | |
552 (mime/editor-mode) | |
553 )) | |
554 | |
555 (cond (running-xemacs | |
556 (defconst mime-editor/minor-mime-map nil "Keymap for MIME commands.") | |
557 (or mime-editor/minor-mime-map | |
558 (progn | |
559 (setq mime-editor/minor-mime-map | |
560 (make-sparse-keymap 'mime-editor/minor-mime-map)) | |
561 (define-key | |
562 mime-editor/minor-mime-map mime-prefix mime-editor/mime-map) | |
563 )) | |
564 (add-minor-mode 'mime/editor-mode-flag | |
565 '((" MIME-Edit " mime-editor/transfer-level-string)) | |
566 mime-editor/minor-mime-map | |
567 nil | |
568 'mime-editor/toggle-mode) | |
569 ) | |
570 (t | |
571 (set-alist 'minor-mode-alist | |
572 'mime/editor-mode-flag | |
573 '((" MIME-Edit " mime-editor/transfer-level-string)))) | |
574 ) | |
575 | |
576 (defconst mime-editor/menu-title "MIME-Edit") | |
577 | |
578 (defconst mime-editor/menu-list | |
579 '((mime-help "Describe MIME editor mode" mime-editor/help) | |
580 (file "Insert File" mime-editor/insert-file) | |
581 (external "Insert External" mime-editor/insert-external) | |
582 (voice "Insert Voice" mime-editor/insert-voice) | |
583 (message "Insert Message" mime-editor/insert-message) | |
584 (mail "Insert Mail" mime-editor/insert-mail) | |
585 (signature "Insert Signature" mime-editor/insert-signature) | |
586 (text "Insert Text" mime-editor/insert-text) | |
587 (tag "Insert Tag" mime-editor/insert-tag) | |
588 (alternative "Enclose as alternative" | |
589 mime-editor/enclose-alternative-region) | |
590 (parallel "Enclose as parallel" mime-editor/enclose-parallel-region) | |
591 (mixed "Enclose as serial" mime-editor/enclose-mixed-region) | |
592 (digest "Enclose as digest" mime-editor/enclose-digest-region) | |
593 (signed "Enclose as signed" mime-editor/enclose-signed-region) | |
594 (encrypted "Enclose as encrypted" mime-editor/enclose-encrypted-region) | |
595 (quote "Verbatim region" mime-editor/enclose-quote-region) | |
596 (key "Insert Public Key" mime-editor/insert-key) | |
597 (split "About split" mime-editor/set-split) | |
598 (sign "About sign" mime-editor/set-sign) | |
599 (encrypt "About encryption" mime-editor/set-encrypt) | |
600 (preview "Preview Message" mime-editor/preview-message) | |
601 (level "Toggle transfer-level" mime-editor/toggle-transfer-level) | |
602 ) | |
603 "MIME-edit menubar entry.") | |
604 | |
605 (defun mime-editor/define-menu-for-emacs19 () | |
606 "Define menu for Emacs 19." | |
607 (define-key (current-local-map) [menu-bar mime-edit] | |
608 (cons mime-editor/menu-title | |
609 (make-sparse-keymap mime-editor/menu-title))) | |
610 (mapcar (function | |
611 (lambda (item) | |
612 (define-key (current-local-map) | |
613 (vector 'menu-bar 'mime-edit (car item)) | |
614 (cons (nth 1 item)(nth 2 item)) | |
615 ) | |
616 )) | |
617 (reverse mime-editor/menu-list) | |
618 )) | |
619 | |
620 ;;; modified by Pekka Marjola <pema@iki.fi> | |
621 ;;; 1995/9/5 (c.f. [tm-en:69]) | |
622 (defun mime-editor/define-menu-for-xemacs () | |
623 "Define menu for Emacs 19." | |
624 (cond ((featurep 'menubar) | |
625 (make-local-variable 'current-menubar) | |
626 (set-buffer-menubar current-menubar) | |
627 (add-submenu nil | |
628 (cons mime-editor/menu-title | |
629 (mapcar (function | |
630 (lambda (item) | |
631 (vector (nth 1 item)(nth 2 item) | |
632 mime/editor-mode-flag) | |
633 )) | |
634 mime-editor/menu-list))) | |
635 ))) | |
636 | |
637 ;;; modified by Steven L. Baur <steve@miranova.com> | |
638 ;;; 1995/12/6 (c.f. [tm-en:209]) | |
639 (if (and running-xemacs (not (boundp 'mime-editor/popup-menu-for-xemacs))) | |
640 (setq mime-editor/popup-menu-for-xemacs | |
641 (append '("MIME Commands" "---") | |
642 (mapcar (function (lambda (item) | |
643 (vector (nth 1 item) | |
644 (nth 2 item) | |
645 t))) | |
646 mime-editor/menu-list))) | |
647 ) | |
648 ;;; end | |
649 | |
650 | |
651 ;;; @ functions | |
652 ;;; | |
653 | |
654 ;;;###autoload | |
655 (defun mime/editor-mode () | |
656 "MIME minor mode for editing the tagged MIME message. | |
657 | |
658 In this mode, basically, the message is composed in the tagged MIME | |
659 format. The message tag looks like: | |
660 | |
661 `--[[text/plain; charset=ISO-2022-JP][7bit]]'. | |
662 | |
663 The tag specifies the MIME content type, subtype, optional parameters | |
664 and transfer encoding of the message following the tag. Messages | |
665 without any tag are treated as `text/plain' by default. Charset and | |
666 transfer encoding are automatically defined unless explicitly | |
667 specified. Binary messages such as audio and image are usually hidden. | |
668 The messages in the tagged MIME format are automatically translated | |
669 into a MIME compliant message when exiting this mode. | |
670 | |
671 Available charsets depend on Emacs version being used. The following | |
672 lists the available charsets of each emacs. | |
673 | |
674 EMACS 18: US-ASCII is only available. | |
675 NEmacs: US-ASCII and ISO-2022-JP are available. | |
676 EMACS 19: US-ASCII and ISO-8859-1 (or other charset) are available. | |
677 XEmacs 19: US-ASCII and ISO-8859-1 (or other charset) are available. | |
678 Mule: US-ASCII, ISO-8859-* (except for ISO-8859-5), KOI8-R, | |
679 ISO-2022-JP, ISO-2022-JP-2, ISO-2022-KR, BIG5 and | |
680 ISO-2022-INT-1 are available. | |
681 | |
682 ISO-2022-JP-2 and ISO-2022-INT-1 charsets used in mule is expected to | |
683 be used to represent multilingual text in intermixed manner. Any | |
684 languages that has no registered charset are represented as either | |
685 ISO-2022-JP-2 or ISO-2022-INT-1 in mule. | |
686 | |
687 If you want to use non-ISO-8859-1 charset in EMACS 19 or XEmacs 19, | |
688 please set variable `default-mime-charset'. This variable must be | |
689 symbol of which name is a MIME charset. | |
690 | |
691 If you want to add more charsets in mule, please set variable | |
692 `charsets-mime-charset-alist'. This variable must be alist of which | |
693 key is list of leading-char/charset and value is symbol of MIME | |
694 charset. (leading-char is a term of MULE 1.* and 2.*. charset is a | |
695 term of XEmacs/mule, mule merged EMACS and MULE 3.*) If name of | |
696 coding-system is different as MIME charset, please set variable | |
697 `mime-charset-coding-system-alist'. This variable must be alist of | |
698 which key is MIME charset and value is coding-system. | |
699 | |
700 Following commands are available in addition to major mode commands: | |
701 \\[mime-editor/insert-text] insert a text message. | |
702 \\[mime-editor/insert-file] insert a (binary) file. | |
703 \\[mime-editor/insert-external] insert a reference to external body. | |
704 \\[mime-editor/insert-voice] insert a voice message. | |
705 \\[mime-editor/insert-message] insert a mail or news message. | |
706 \\[mime-editor/insert-mail] insert a mail message. | |
707 \\[mime-editor/insert-signature] insert a signature file at end. | |
708 \\[mime-editor/insert-tag] insert a new MIME tag. | |
709 \\[mime-editor/enclose-alternative-region] enclose as multipart/alternative. | |
710 \\[mime-editor/enclose-parallel-region] enclose as multipart/parallel. | |
711 \\[mime-editor/enclose-mixed-region] enclose as multipart/mixed. | |
712 \\[mime-editor/enclose-digest-region] enclose as multipart/digest. | |
713 \\[mime-editor/enclose-signed-region] enclose as PGP signed. | |
714 \\[mime-editor/enclose-encrypted-region] enclose as PGP encrypted. | |
715 \\[mime-editor/insert-key] insert PGP public key. | |
716 \\[mime-editor/preview-message] preview editing MIME message. | |
717 \\[mime-editor/exit] exit and translate into a MIME compliant message. | |
718 \\[mime-editor/maybe-translate] exit and translate if in MIME mode, then split. | |
719 \\[mime-editor/help] show this help. | |
720 | |
721 Additional commands are available in some major modes: | |
722 C-c C-c exit, translate and run the original command. | |
723 C-c C-s exit, translate and run the original command. | |
724 | |
725 The following is a message example written in the tagged MIME format. | |
726 TABs at the beginning of the line are not a part of the message: | |
727 | |
728 This is a conventional plain text. It should be translated | |
729 into text/plain. | |
730 --[[text/plain]] | |
731 This is also a plain text. But, it is explicitly specified as | |
732 is. | |
733 --[[text/plain; charset=ISO-2022-JP]] | |
734 これは charset を ISO-2022-JP に指定した日本語の plain テキス | |
735 トです. | |
736 --[[text/richtext]] | |
737 <center>This is a richtext.</center> | |
738 --[[image/gif][base64]]^M...image encoded in base64 here... | |
739 --[[audio/basic][base64]]^M...audio encoded in base64 here... | |
740 | |
741 User customizable variables (not documented all of them): | |
742 mime-prefix | |
743 Specifies a key prefix for MIME minor mode commands. | |
744 | |
745 mime-ignore-preceding-spaces | |
746 Preceding white spaces in a message body are ignored if non-nil. | |
747 | |
748 mime-ignore-trailing-spaces | |
749 Trailing white spaces in a message body are ignored if non-nil. | |
750 | |
751 mime-auto-fill-header | |
752 Fill header fields that contain encoded-words if non-nil. | |
753 | |
754 mime-auto-hide-body | |
755 Hide a non-textual body message encoded in base64 after insertion | |
756 if non-nil. | |
757 | |
758 mime-editor/voice-recorder | |
759 Specifies a function to record a voice message and encode it. | |
760 The function `mime-editor/voice-recorder-for-sun' is for Sun | |
761 SparcStations. | |
762 | |
763 mime/editor-mode-hook | |
764 Turning on MIME mode calls the value of mime/editor-mode-hook, if | |
765 it is non-nil. | |
766 | |
767 mime-editor/translate-hook | |
768 The value of mime-editor/translate-hook is called just before translating | |
769 the tagged MIME format into a MIME compliant message if it is | |
770 non-nil. If the hook call the function mime-editor/insert-signature, | |
771 the signature file will be inserted automatically. | |
772 | |
773 mime-editor/exit-hook | |
774 Turning off MIME mode calls the value of mime-editor/exit-hook, if it is | |
775 non-nil." | |
776 (interactive) | |
777 (if mime/editor-mode-flag | |
778 (error "You are already editing a MIME message.") | |
779 (setq mime/editor-mode-flag t) | |
780 ;; Remember old key bindings. | |
781 (if running-xemacs | |
782 (use-local-map (or (current-local-map) (make-sparse-keymap))) | |
783 (make-local-variable 'mime/editor-mode-old-local-map) | |
784 (setq mime/editor-mode-old-local-map (current-local-map)) | |
785 ;; Add MIME commands to current local map. | |
786 (use-local-map (copy-keymap (or (current-local-map) | |
787 (make-sparse-keymap)))) | |
788 ) | |
789 (if (not (lookup-key (current-local-map) mime-prefix)) | |
790 (define-key (current-local-map) mime-prefix mime-editor/mime-map)) | |
791 | |
792 ;; Set transfer level into mode line | |
793 ;; | |
794 (setq mime-editor/transfer-level-string | |
795 (mime/encoding-name mime-editor/transfer-level 'not-omit)) | |
796 (force-mode-line-update) | |
797 | |
798 ;; Define menu. Menus for other emacs implementations are | |
799 ;; welcome. | |
800 (cond (running-xemacs | |
801 (mime-editor/define-menu-for-xemacs)) | |
802 ((>= emacs-major-version 19) | |
803 (mime-editor/define-menu-for-emacs19) | |
804 )) | |
805 ;; end | |
806 | |
807 (enable-invisible) | |
808 | |
809 ;; I don't care about saving these. | |
810 (setq paragraph-start | |
811 (regexp-or mime-editor/single-part-tag-regexp | |
812 paragraph-start)) | |
813 (setq paragraph-separate | |
814 (regexp-or mime-editor/single-part-tag-regexp | |
815 paragraph-separate)) | |
816 (run-hooks 'mime/editor-mode-hook) | |
817 (message | |
818 (substitute-command-keys | |
819 "Type \\[mime-editor/exit] to exit MIME mode, and type \\[mime-editor/help] to get help.")) | |
820 )) | |
821 | |
822 ;;;###autoload | |
823 (defalias 'edit-mime 'mime/editor-mode) ; for convenience | |
824 (defalias 'mime-mode 'mime/editor-mode) ; for convenience | |
825 | |
826 (defun mime-editor/exit (&optional nomime no-error) | |
827 "Translate the tagged MIME message into a MIME compliant message. | |
828 With no argument encode a message in the buffer into MIME, otherwise | |
829 just return to previous mode." | |
830 (interactive "P") | |
831 (if (not mime/editor-mode-flag) | |
832 (if (null no-error) | |
833 (error "You aren't editing a MIME message.") | |
834 ) | |
835 (if (not nomime) | |
836 (progn | |
837 (run-hooks 'mime-editor/translate-hook) | |
838 (mime-editor/translate-buffer))) | |
839 ;; Restore previous state. | |
840 (setq mime/editor-mode-flag nil) | |
841 (cond (running-xemacs | |
842 (delete-menu-item (list mime-editor/menu-title))) | |
843 (t | |
844 (use-local-map mime/editor-mode-old-local-map))) | |
845 | |
846 (end-of-invisible) | |
847 (set-buffer-modified-p (buffer-modified-p)) | |
848 (run-hooks 'mime-editor/exit-hook) | |
849 (message "Exit MIME editor mode.") | |
850 )) | |
851 | |
852 (defun mime-editor/maybe-translate () | |
853 (interactive) | |
854 (mime-editor/exit nil t) | |
855 (call-interactively 'mime-editor/maybe-split-and-send) | |
856 ) | |
857 | |
858 (defun mime-editor/help () | |
859 "Show help message about MIME mode." | |
860 (interactive) | |
861 (with-output-to-temp-buffer "*Help*" | |
862 (princ "MIME editor mode:\n") | |
863 (princ (documentation 'mime/editor-mode)) | |
864 (print-help-return-message))) | |
865 | |
866 (defun mime-editor/insert-text () | |
867 "Insert a text message. | |
868 Charset is automatically obtained from the `mime/lc-charset-alist'." | |
869 (interactive) | |
870 (let ((ret (mime-editor/insert-tag "text" nil nil))) | |
871 (if ret | |
872 (progn | |
873 (if (looking-at mime-editor/single-part-tag-regexp) | |
874 (progn | |
875 ;; Make a space between the following message. | |
876 (insert "\n") | |
877 (forward-char -1) | |
878 )) | |
879 (if (and (member (second ret) '("enriched" "richtext")) | |
880 (fboundp 'enriched-mode) | |
881 ) | |
882 (enriched-mode t) | |
883 (if (boundp 'enriched-mode) | |
884 (enriched-mode nil) | |
885 )))))) | |
886 | |
887 (defun mime-editor/insert-file (file) | |
888 "Insert a message from a file." | |
889 (interactive "fInsert file as MIME message: ") | |
890 (let* ((guess (mime-find-file-type file)) | |
891 (pritype (nth 0 guess)) | |
892 (subtype (nth 1 guess)) | |
893 (parameters (nth 2 guess)) | |
894 (default (nth 3 guess)) ;Guess encoding from its file name. | |
895 (disposition-type (nth 4 guess)) | |
896 (disposition-params (nth 5 guess)) | |
897 (encoding | |
898 (if (not (interactive-p)) | |
899 default | |
900 (completing-read | |
901 (concat "What transfer encoding" | |
902 (if default | |
903 (concat " (default " | |
904 (if (string-equal default "") | |
905 "\"\"" | |
906 default) | |
907 ")" | |
908 )) | |
909 ": ") | |
910 mime-file-encoding-method-alist nil t nil)))) | |
911 (if (string-equal encoding "") | |
912 (setq encoding default)) | |
913 (if (or (consp parameters) (stringp disposition-type)) | |
914 (let ((rest parameters) cell attribute value) | |
915 (setq parameters "") | |
916 (while rest | |
917 (setq cell (car rest)) | |
918 (setq attribute (car cell)) | |
919 (setq value (cdr cell)) | |
920 (if (eq value 'file) | |
921 (setq value (std11-wrap-as-quoted-string | |
922 (file-name-nondirectory file))) | |
923 ) | |
924 (setq parameters (concat parameters "; " attribute "=" value)) | |
925 (setq rest (cdr rest)) | |
926 ) | |
927 (if disposition-type | |
928 (progn | |
929 (setq parameters | |
930 (concat parameters "\n" | |
931 "Content-Disposition: " disposition-type)) | |
932 (setq rest disposition-params) | |
933 (while rest | |
934 (setq cell (car rest)) | |
935 (setq attribute (car cell)) | |
936 (setq value (cdr cell)) | |
937 (if (eq value 'file) | |
938 (setq value (std11-wrap-as-quoted-string | |
939 (file-name-nondirectory file))) | |
940 ) | |
941 (setq parameters | |
942 (concat parameters "; " attribute "=" value)) | |
943 (setq rest (cdr rest)) | |
944 ) | |
945 )) | |
946 )) | |
947 (mime-editor/insert-tag pritype subtype parameters) | |
948 (mime-editor/insert-binary-file file encoding) | |
949 )) | |
950 | |
951 (defun mime-editor/insert-external () | |
952 "Insert a reference to external body." | |
953 (interactive) | |
954 (mime-editor/insert-tag "message" "external-body" nil ";\n\t") | |
955 ;;(forward-char -1) | |
956 ;;(insert "Content-Description: " (read-string "Content-Description: ") "\n") | |
957 ;;(forward-line 1) | |
958 (let* ((pritype (mime-prompt-for-type)) | |
959 (subtype (mime-prompt-for-subtype pritype)) | |
960 (parameters (mime-prompt-for-parameters pritype subtype ";\n\t"))) | |
961 (and pritype | |
962 subtype | |
963 (insert "Content-Type: " | |
964 pritype "/" subtype (or parameters "") "\n"))) | |
965 (if (and (not (eobp)) | |
966 (not (looking-at mime-editor/single-part-tag-regexp))) | |
967 (insert (mime-make-text-tag) "\n"))) | |
968 | |
969 (defun mime-editor/insert-voice () | |
970 "Insert a voice message." | |
971 (interactive) | |
972 (let ((encoding | |
973 (completing-read | |
974 "What transfer encoding: " | |
975 mime-file-encoding-method-alist nil t nil))) | |
976 (mime-editor/insert-tag "audio" "basic" nil) | |
977 (mime-editor/define-encoding encoding) | |
978 (save-restriction | |
979 (narrow-to-region (1- (point))(point)) | |
980 (unwind-protect | |
981 (funcall mime-editor/voice-recorder encoding) | |
982 (progn | |
983 (insert "\n") | |
984 (invisible-region (point-min)(point-max)) | |
985 (goto-char (point-max)) | |
986 ))))) | |
987 | |
988 (defun mime-editor/insert-signature (&optional arg) | |
989 "Insert a signature file." | |
990 (interactive "P") | |
991 (let ((signature-insert-hook | |
992 (function | |
993 (lambda () | |
994 (apply (function mime-editor/insert-tag) | |
995 (mime-find-file-type signature-file-name)) | |
996 ))) | |
997 ) | |
998 (insert-signature arg) | |
999 )) | |
1000 | |
1001 | |
1002 ;; Insert a new tag around a point. | |
1003 | |
1004 (defun mime-editor/insert-tag (&optional pritype subtype parameters delimiter) | |
1005 "Insert new MIME tag and return a list of PRITYPE, SUBTYPE, and PARAMETERS. | |
1006 If nothing is inserted, return nil." | |
1007 (interactive) | |
1008 (let ((p (point))) | |
1009 (mime-editor/goto-tag) | |
1010 (if (and (re-search-forward mime-editor/tag-regexp nil t) | |
1011 (< (match-beginning 0) p) | |
1012 (< p (match-end 0)) | |
1013 ) | |
1014 (goto-char (match-beginning 0)) | |
1015 (goto-char p) | |
1016 )) | |
1017 (let ((oldtag nil) | |
1018 (newtag nil) | |
1019 (current (point)) | |
1020 ) | |
1021 (setq pritype | |
1022 (or pritype | |
1023 (mime-prompt-for-type))) | |
1024 (setq subtype | |
1025 (or subtype | |
1026 (mime-prompt-for-subtype pritype))) | |
1027 (setq parameters | |
1028 (or parameters | |
1029 (mime-prompt-for-parameters pritype subtype delimiter))) | |
1030 ;; Make a new MIME tag. | |
1031 (setq newtag (mime-make-tag pritype subtype parameters)) | |
1032 ;; Find an current MIME tag. | |
1033 (setq oldtag | |
1034 (save-excursion | |
1035 (if (mime-editor/goto-tag) | |
1036 (buffer-substring (match-beginning 0) (match-end 0)) | |
1037 ;; Assume content type is 'text/plan'. | |
1038 (mime-make-tag "text" "plain") | |
1039 ))) | |
1040 ;; We are only interested in TEXT. | |
1041 (if (and oldtag | |
1042 (not (mime-test-content-type | |
1043 (mime-editor/get-contype oldtag) "text"))) | |
1044 (setq oldtag nil)) | |
1045 ;; Make a new tag. | |
1046 (if (or (not oldtag) ;Not text | |
1047 (or mime-ignore-same-text-tag | |
1048 (not (string-equal oldtag newtag)))) | |
1049 (progn | |
1050 ;; Mark the beginning of the tag for convenience. | |
1051 (push-mark (point) 'nomsg) | |
1052 (insert newtag "\n") | |
1053 (list pritype subtype parameters) ;New tag is created. | |
1054 ) | |
1055 ;; Restore previous point. | |
1056 (goto-char current) | |
1057 nil ;Nothing is created. | |
1058 ) | |
1059 )) | |
1060 | |
1061 (defun mime-editor/insert-binary-file (file &optional encoding) | |
1062 "Insert binary FILE at point. | |
1063 Optional argument ENCODING specifies an encoding method such as base64." | |
1064 (let* ((tagend (1- (point))) ;End of the tag | |
1065 (hide-p (and mime-auto-hide-body | |
1066 (stringp encoding) | |
1067 (not | |
1068 (let ((en (downcase encoding))) | |
1069 (or (string-equal en "7bit") | |
1070 (string-equal en "8bit") | |
1071 (string-equal en "binary") | |
1072 ))))) | |
1073 ) | |
1074 (save-restriction | |
1075 (narrow-to-region tagend (point)) | |
1076 (mime-insert-encoded-file file encoding) | |
1077 (if hide-p | |
1078 (progn | |
1079 (invisible-region (point-min) (point-max)) | |
1080 (goto-char (point-max)) | |
1081 ) | |
1082 (goto-char (point-max)) | |
1083 )) | |
1084 (or hide-p | |
1085 (looking-at mime-editor/tag-regexp) | |
1086 (= (point)(point-max)) | |
1087 (mime-editor/insert-tag "text" "plain") | |
1088 ) | |
1089 ;; Define encoding even if it is 7bit. | |
1090 (if (stringp encoding) | |
1091 (save-excursion | |
1092 (goto-char tagend) ; Make sure which line the tag is on. | |
1093 (mime-editor/define-encoding encoding) | |
1094 )) | |
1095 )) | |
1096 | |
1097 | |
1098 ;; Commands work on a current message flagment. | |
1099 | |
1100 (defun mime-editor/goto-tag () | |
1101 "Search for the beginning of the tagged MIME message." | |
1102 (let ((current (point)) multipart) | |
1103 (if (looking-at mime-editor/tag-regexp) | |
1104 t | |
1105 ;; At first, go to the end. | |
1106 (cond ((re-search-forward mime-editor/beginning-tag-regexp nil t) | |
1107 (goto-char (1- (match-beginning 0))) ;For multiline tag | |
1108 ) | |
1109 (t | |
1110 (goto-char (point-max)) | |
1111 )) | |
1112 ;; Then search for the beginning. | |
1113 (re-search-backward mime-editor/end-tag-regexp nil t) | |
1114 (or (looking-at mime-editor/beginning-tag-regexp) | |
1115 ;; Restore previous point. | |
1116 (progn | |
1117 (goto-char current) | |
1118 nil | |
1119 )) | |
1120 ))) | |
1121 | |
1122 (defun mime-editor/content-beginning () | |
1123 "Return the point of the beginning of content." | |
1124 (save-excursion | |
1125 (let ((beg (save-excursion | |
1126 (beginning-of-line) (point)))) | |
1127 (if (mime-editor/goto-tag) | |
1128 (let ((top (point))) | |
1129 (goto-char (match-end 0)) | |
1130 (if (and (= beg top) | |
1131 (= (following-char) ?\^M)) | |
1132 (point) | |
1133 (forward-line 1) | |
1134 (point))) | |
1135 ;; Default text/plain tag. | |
1136 (goto-char (point-min)) | |
1137 (re-search-forward | |
1138 (concat "\n" (regexp-quote mail-header-separator) | |
1139 (if mime-ignore-preceding-spaces | |
1140 "[ \t\n]*\n" "\n")) nil 'move) | |
1141 (point)) | |
1142 ))) | |
1143 | |
1144 (defun mime-editor/content-end () | |
1145 "Return the point of the end of content." | |
1146 (save-excursion | |
1147 (let ((beg (point))) | |
1148 (if (mime-editor/goto-tag) | |
1149 (let ((top (point))) | |
1150 (goto-char (match-end 0)) | |
1151 (if (invisible-p (point)) | |
1152 (next-visible-point (point)) | |
1153 ;; Move to the end of this text. | |
1154 (if (re-search-forward mime-editor/tag-regexp nil 'move) | |
1155 ;; Don't forget a multiline tag. | |
1156 (goto-char (match-beginning 0)) | |
1157 ) | |
1158 (point) | |
1159 )) | |
1160 ;; Assume the message begins with text/plain. | |
1161 (goto-char (mime-editor/content-beginning)) | |
1162 (if (re-search-forward mime-editor/tag-regexp nil 'move) | |
1163 ;; Don't forget a multiline tag. | |
1164 (goto-char (match-beginning 0))) | |
1165 (point)) | |
1166 ))) | |
1167 | |
1168 (defun mime-editor/define-charset (charset) | |
1169 "Set charset of current tag to CHARSET." | |
1170 (save-excursion | |
1171 (if (mime-editor/goto-tag) | |
1172 (let ((tag (buffer-substring (match-beginning 0) (match-end 0)))) | |
1173 (delete-region (match-beginning 0) (match-end 0)) | |
1174 (insert | |
1175 (mime-create-tag | |
1176 (mime-editor/set-parameter | |
1177 (mime-editor/get-contype tag) | |
1178 "charset" (upcase (symbol-name charset))) | |
1179 (mime-editor/get-encoding tag))) | |
1180 )))) | |
1181 | |
1182 (defun mime-editor/define-encoding (encoding) | |
1183 "Set encoding of current tag to ENCODING." | |
1184 (save-excursion | |
1185 (if (mime-editor/goto-tag) | |
1186 (let ((tag (buffer-substring (match-beginning 0) (match-end 0)))) | |
1187 (delete-region (match-beginning 0) (match-end 0)) | |
1188 (insert (mime-create-tag (mime-editor/get-contype tag) encoding))) | |
1189 ))) | |
1190 | |
1191 (defun mime-editor/choose-charset () | |
1192 "Choose charset of a text following current point." | |
1193 (detect-mime-charset-region (point) (mime-editor/content-end)) | |
1194 ) | |
1195 | |
1196 (defun mime-make-text-tag (&optional subtype) | |
1197 "Make a tag for a text after current point. | |
1198 Subtype of text type can be specified by an optional argument SUBTYPE. | |
1199 Otherwise, it is obtained from mime-content-types." | |
1200 (let* ((pritype "text") | |
1201 (subtype (or subtype | |
1202 (car (car (cdr (assoc pritype mime-content-types))))))) | |
1203 ;; Charset should be defined later. | |
1204 (mime-make-tag pritype subtype))) | |
1205 | |
1206 | |
1207 ;; Tag handling functions | |
1208 | |
1209 (defun mime-make-tag (pritype subtype &optional parameters encoding) | |
1210 "Make a tag of MIME message of PRITYPE, SUBTYPE and optional PARAMETERS." | |
1211 (mime-create-tag (concat (or pritype "") "/" (or subtype "") | |
1212 (or parameters "")) | |
1213 encoding)) | |
1214 | |
1215 (defun mime-create-tag (contype &optional encoding) | |
1216 "Make a tag with CONTENT-TYPE and optional ENCODING." | |
1217 (format (if encoding mime-tag-format-with-encoding mime-tag-format) | |
1218 contype encoding)) | |
1219 | |
1220 (defun mime-editor/get-contype (tag) | |
1221 "Return Content-Type (including parameters) of TAG." | |
1222 (and (stringp tag) | |
1223 (or (string-match mime-editor/single-part-tag-regexp tag) | |
1224 (string-match mime-editor/multipart-beginning-regexp tag) | |
1225 (string-match mime-editor/multipart-end-regexp tag) | |
1226 ) | |
1227 (substring tag (match-beginning 1) (match-end 1)) | |
1228 )) | |
1229 | |
1230 (defun mime-editor/get-encoding (tag) | |
1231 "Return encoding of TAG." | |
1232 (and (stringp tag) | |
1233 (string-match mime-editor/single-part-tag-regexp tag) | |
1234 (match-beginning 3) | |
1235 (not (= (match-beginning 3) (match-end 3))) | |
1236 (substring tag (match-beginning 3) (match-end 3)))) | |
1237 | |
1238 (defun mime-get-parameter (contype parameter) | |
1239 "For given CONTYPE return value for PARAMETER. | |
1240 Nil if no such parameter." | |
1241 (if (string-match | |
1242 (concat | |
1243 ";[ \t\n]*" | |
1244 (regexp-quote parameter) | |
1245 "[ \t\n]*=[ \t\n]*\\([^\" \t\n;]*\\|\"[^\"]*\"\\)\\([ \t\n]*;\\|$\\)") | |
1246 contype) | |
1247 (substring contype (match-beginning 1) (match-end 1)) | |
1248 nil ;No such parameter | |
1249 )) | |
1250 | |
1251 (defun mime-editor/set-parameter (contype parameter value) | |
1252 "For given CONTYPE set PARAMETER to VALUE." | |
1253 (let (ctype opt-fields) | |
1254 (if (string-match "\n[^ \t\n\r]+:" contype) | |
1255 (setq ctype (substring contype 0 (match-beginning 0)) | |
1256 opt-fields (substring contype (match-beginning 0))) | |
1257 (setq ctype contype) | |
1258 ) | |
1259 (if (string-match | |
1260 (concat | |
1261 ";[ \t\n]*\\(" | |
1262 (regexp-quote parameter) | |
1263 "[ \t\n]*=[ \t\n]*\\([^\" \t\n;]*\\|\"[^\"]*\"\\)\\)[ \t\n]*\\(;\\|$\\)") | |
1264 ctype) | |
1265 ;; Change value | |
1266 (concat (substring ctype 0 (match-beginning 1)) | |
1267 parameter "=" value | |
1268 (substring contype (match-end 1)) | |
1269 opt-fields) | |
1270 (concat ctype "; " parameter "=" value opt-fields) | |
1271 ))) | |
1272 | |
1273 (defun mime-strip-parameters (contype) | |
1274 "Return primary content-type and subtype without parameters for CONTYPE." | |
1275 (if (string-match "^[ \t]*\\([^; \t\n]*\\)" contype) | |
1276 (substring contype (match-beginning 1) (match-end 1)) nil)) | |
1277 | |
1278 (defun mime-test-content-type (contype type &optional subtype) | |
1279 "Test if CONTYPE is a TYPE and an optional SUBTYPE." | |
1280 (and (stringp contype) | |
1281 (stringp type) | |
1282 (string-match | |
1283 (concat "^[ \t]*" (downcase type) "/" (downcase (or subtype ""))) | |
1284 (downcase contype)))) | |
1285 | |
1286 | |
1287 ;; Basic functions | |
1288 | |
1289 (defun mime-find-file-type (file) | |
1290 "Guess Content-Type, subtype, and parameters from FILE." | |
1291 (let ((guess nil) | |
1292 (guesses mime-file-types)) | |
1293 (while (and (not guess) guesses) | |
1294 (if (string-match (car (car guesses)) file) | |
1295 (setq guess (cdr (car guesses)))) | |
1296 (setq guesses (cdr guesses))) | |
1297 guess | |
1298 )) | |
1299 | |
1300 (defun mime-prompt-for-type () | |
1301 "Ask for Content-type." | |
1302 (let ((type "")) | |
1303 ;; Repeat until primary content type is specified. | |
1304 (while (string-equal type "") | |
1305 (setq type | |
1306 (completing-read "What content type: " | |
1307 mime-content-types | |
1308 nil | |
1309 'require-match ;Type must be specified. | |
1310 nil | |
1311 )) | |
1312 (if (string-equal type "") | |
1313 (progn | |
1314 (message "Content type is required.") | |
1315 (beep) | |
1316 (sit-for 1) | |
1317 )) | |
1318 ) | |
1319 type | |
1320 )) | |
1321 | |
1322 (defun mime-prompt-for-subtype (pritype) | |
1323 "Ask for Content-type subtype of Content-Type PRITYPE." | |
1324 (let* ((default (car (car (cdr (assoc pritype mime-content-types))))) | |
1325 (answer | |
1326 (completing-read | |
1327 (if default | |
1328 (concat | |
1329 "What content subtype: (default " default ") ") | |
1330 "What content subtype: ") | |
1331 (cdr (assoc pritype mime-content-types)) | |
1332 nil | |
1333 'require-match ;Subtype must be specified. | |
1334 nil | |
1335 ))) | |
1336 (if (string-equal answer "") default answer))) | |
1337 | |
1338 (defun mime-prompt-for-parameters (pritype subtype &optional delimiter) | |
1339 "Ask for Content-type parameters of Content-Type PRITYPE and SUBTYPE. | |
1340 Optional DELIMITER specifies parameter delimiter (';' by default)." | |
1341 (let* ((delimiter (or delimiter "; ")) | |
1342 (parameters | |
1343 (mapconcat | |
1344 (function identity) | |
1345 (delq nil | |
1346 (mime-prompt-for-parameters-1 | |
1347 (cdr (assoc subtype | |
1348 (cdr (assoc pritype mime-content-types)))))) | |
1349 delimiter | |
1350 ))) | |
1351 (if (and (stringp parameters) | |
1352 (not (string-equal parameters ""))) | |
1353 (concat delimiter parameters) | |
1354 "" ;"" if no parameters | |
1355 ))) | |
1356 | |
1357 (defun mime-prompt-for-parameters-1 (optlist) | |
1358 (apply (function append) | |
1359 (mapcar (function mime-prompt-for-parameter) optlist))) | |
1360 | |
1361 (defun mime-prompt-for-parameter (parameter) | |
1362 "Ask for PARAMETER. | |
1363 Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))." | |
1364 (let* ((prompt (car parameter)) | |
1365 (choices (mapcar (function | |
1366 (lambda (e) | |
1367 (if (consp e) e (list e)))) | |
1368 (cdr parameter))) | |
1369 (default (car (car choices))) | |
1370 (answer nil)) | |
1371 (if choices | |
1372 (progn | |
1373 (setq answer | |
1374 (completing-read | |
1375 (concat "What " prompt | |
1376 ": (default " | |
1377 (if (string-equal default "") "\"\"" default) | |
1378 ") ") | |
1379 choices nil nil "")) | |
1380 ;; If nothing is selected, use default. | |
1381 (if (string-equal answer "") | |
1382 (setq answer default))) | |
1383 (setq answer | |
1384 (read-string (concat "What " prompt ": ")))) | |
1385 (cons (if (and answer | |
1386 (not (string-equal answer ""))) | |
1387 (concat prompt "=" | |
1388 ;; Note: control characters ignored! | |
1389 (if (string-match mime-tspecials-regexp answer) | |
1390 (concat "\"" answer "\"") answer))) | |
1391 (mime-prompt-for-parameters-1 (cdr (assoc answer (cdr parameter))))) | |
1392 )) | |
1393 | |
1394 (defun mime-flag-region (from to flag) | |
1395 "Hides or shows lines from FROM to TO, according to FLAG. | |
1396 If FLAG is `\\n' (newline character) then text is shown, | |
1397 while if FLAG is `\\^M' (control-M) the text is hidden." | |
1398 (let ((buffer-read-only nil) ;Okay even if write protected. | |
1399 (modp (buffer-modified-p))) | |
1400 (unwind-protect | |
1401 (subst-char-in-region from to | |
1402 (if (= flag ?\n) ?\^M ?\n) | |
1403 flag t) | |
1404 (set-buffer-modified-p modp)))) | |
1405 | |
1406 | |
1407 ;;; @ Translate the tagged MIME messages into a MIME compliant message. | |
1408 ;;; | |
1409 | |
1410 (defvar mime-editor/translate-buffer-hook | |
1411 '(mime-editor/pgp-enclose-buffer | |
1412 mime-editor/translate-header | |
1413 mime-editor/translate-body)) | |
1414 | |
1415 (defun mime-editor/translate-header () | |
1416 "Encode the message header into network representation." | |
1417 (mime/encode-message-header 'code-conversion) | |
1418 (run-hooks 'mime-editor/translate-header-hook) | |
1419 ) | |
1420 | |
1421 (defun mime-editor/translate-buffer () | |
1422 "Encode the tagged MIME message in current buffer in MIME compliant message." | |
1423 (interactive) | |
1424 (if (catch 'mime-editor/error | |
1425 (save-excursion | |
1426 (run-hooks 'mime-editor/translate-buffer-hook) | |
1427 )) | |
1428 (progn | |
1429 (undo) | |
1430 (error "Translation error!") | |
1431 ))) | |
1432 | |
1433 (defun mime-editor/find-inmost () | |
1434 (goto-char (point-min)) | |
1435 (if (re-search-forward mime-editor/multipart-beginning-regexp nil t) | |
1436 (let ((bb (match-beginning 0)) | |
1437 (be (match-end 0)) | |
1438 (type (buffer-substring (match-beginning 1)(match-end 1))) | |
1439 end-exp eb ee) | |
1440 (setq end-exp (format "--}-<<%s>>\n" type)) | |
1441 (widen) | |
1442 (if (re-search-forward end-exp nil t) | |
1443 (progn | |
1444 (setq eb (match-beginning 0)) | |
1445 (setq ee (match-end 0)) | |
1446 ) | |
1447 (setq eb (point-max)) | |
1448 (setq ee (point-max)) | |
1449 ) | |
1450 (narrow-to-region be eb) | |
1451 (goto-char be) | |
1452 (if (re-search-forward mime-editor/multipart-beginning-regexp nil t) | |
1453 (let (ret) | |
1454 (narrow-to-region (match-beginning 0)(point-max)) | |
1455 (mime-editor/find-inmost) | |
1456 ) | |
1457 (widen) | |
1458 (list type bb be eb) | |
1459 )))) | |
1460 | |
1461 (defun mime-editor/process-multipart-1 (boundary) | |
1462 (let ((ret (mime-editor/find-inmost))) | |
1463 (if ret | |
1464 (let ((type (car ret)) | |
1465 (bb (nth 1 ret))(be (nth 2 ret)) | |
1466 (eb (nth 3 ret)) | |
1467 ) | |
1468 (narrow-to-region bb eb) | |
1469 (delete-region bb be) | |
1470 (setq bb (point-min)) | |
1471 (setq eb (point-max)) | |
1472 (widen) | |
1473 (goto-char eb) | |
1474 (if (looking-at mime-editor/multipart-end-regexp) | |
1475 (let ((beg (match-beginning 0)) | |
1476 (end (match-end 0)) | |
1477 ) | |
1478 (delete-region beg end) | |
1479 (or (looking-at mime-editor/beginning-tag-regexp) | |
1480 (eobp) | |
1481 (insert (concat (mime-make-text-tag) "\n")) | |
1482 ))) | |
1483 (cond ((string-equal type "quote") | |
1484 (mime-editor/enquote-region bb eb) | |
1485 ) | |
1486 ((string-equal type "signed") | |
1487 (cond ((eq mime-editor/signing-type 'pgp-elkins) | |
1488 (mime-editor/sign-pgp-elkins bb eb boundary) | |
1489 ) | |
1490 ((eq mime-editor/signing-type 'pgp-kazu) | |
1491 (mime-editor/sign-pgp-kazu bb eb boundary) | |
1492 )) | |
1493 ) | |
1494 ((string-equal type "encrypted") | |
1495 (cond ((eq mime-editor/encrypting-type 'pgp-elkins) | |
1496 (mime-editor/encrypt-pgp-elkins bb eb boundary) | |
1497 ) | |
1498 ((eq mime-editor/encrypting-type 'pgp-kazu) | |
1499 (mime-editor/encrypt-pgp-kazu bb eb boundary) | |
1500 ))) | |
1501 (t | |
1502 (setq boundary | |
1503 (nth 2 (mime-editor/translate-region bb eb | |
1504 boundary t))) | |
1505 (goto-char bb) | |
1506 (insert | |
1507 (format "--[[multipart/%s; | |
1508 boundary=\"%s\"][7bit]]\n" | |
1509 type boundary)) | |
1510 )) | |
1511 boundary)))) | |
1512 | |
1513 (defun mime-editor/enquote-region (beg end) | |
1514 (save-excursion | |
1515 (save-restriction | |
1516 (narrow-to-region beg end) | |
1517 (goto-char beg) | |
1518 (while (re-search-forward mime-editor/single-part-tag-regexp nil t) | |
1519 (let ((tag (buffer-substring (match-beginning 0)(match-end 0)))) | |
1520 (replace-match (concat "- " (substring tag 1))) | |
1521 ))))) | |
1522 | |
1523 (defun mime-editor/dequote-region (beg end) | |
1524 (save-excursion | |
1525 (save-restriction | |
1526 (narrow-to-region beg end) | |
1527 (goto-char beg) | |
1528 (while (re-search-forward | |
1529 mime-editor/quoted-single-part-tag-regexp nil t) | |
1530 (let ((tag (buffer-substring (match-beginning 0)(match-end 0)))) | |
1531 (replace-match (concat "-" (substring tag 2))) | |
1532 ))))) | |
1533 | |
1534 (defun mime-editor/sign-pgp-elkins (beg end boundary) | |
1535 (save-excursion | |
1536 (save-restriction | |
1537 (narrow-to-region beg end) | |
1538 (let* ((ret | |
1539 (mime-editor/translate-region beg end boundary)) | |
1540 (ctype (car ret)) | |
1541 (encoding (nth 1 ret)) | |
1542 (parts (nth 3 ret)) | |
1543 (pgp-boundary (concat "pgp-sign-" boundary)) | |
1544 ) | |
1545 (goto-char beg) | |
1546 (insert (format "Content-Type: %s\n" ctype)) | |
1547 (if encoding | |
1548 (insert (format "Content-Transfer-Encoding: %s\n" encoding)) | |
1549 ) | |
1550 (insert "\n") | |
1551 (or (funcall mime-editor/pgp-sign-function | |
1552 (point-min)(point-max) nil nil pgp-boundary) | |
1553 (throw 'mime-editor/error 'pgp-error) | |
1554 ) | |
1555 )))) | |
1556 | |
1557 (defvar mime-editor/encrypt-recipient-fields-list '("To" "cc")) | |
1558 | |
1559 (defun mime-editor/make-encrypt-recipient-header () | |
1560 (let* ((names mime-editor/encrypt-recipient-fields-list) | |
1561 (values | |
1562 (std11-field-bodies (cons "From" names) | |
1563 nil mail-header-separator)) | |
1564 (from (prog1 | |
1565 (car values) | |
1566 (setq values (cdr values)))) | |
1567 (header (and (stringp from) | |
1568 (if (string-equal from "") | |
1569 "" | |
1570 (format "From: %s\n" from) | |
1571 ))) | |
1572 recipients) | |
1573 (while (and names values) | |
1574 (let ((name (car names)) | |
1575 (value (car values)) | |
1576 ) | |
1577 (and (stringp value) | |
1578 (or (string-equal value "") | |
1579 (progn | |
1580 (setq header (concat header name ": " value "\n") | |
1581 recipients (if recipients | |
1582 (concat recipients " ," value) | |
1583 value)) | |
1584 )))) | |
1585 (setq names (cdr names) | |
1586 values (cdr values)) | |
1587 ) | |
1588 (vector from recipients header) | |
1589 )) | |
1590 | |
1591 (defun mime-editor/encrypt-pgp-elkins (beg end boundary) | |
1592 (save-excursion | |
1593 (save-restriction | |
1594 (let (from recipients header) | |
1595 (let ((ret (mime-editor/make-encrypt-recipient-header))) | |
1596 (setq from (aref ret 0) | |
1597 recipients (aref ret 1) | |
1598 header (aref ret 2)) | |
1599 ) | |
1600 (narrow-to-region beg end) | |
1601 (let* ((ret | |
1602 (mime-editor/translate-region beg end boundary)) | |
1603 (ctype (car ret)) | |
1604 (encoding (nth 1 ret)) | |
1605 (parts (nth 3 ret)) | |
1606 (pgp-boundary (concat "pgp-" boundary)) | |
1607 ) | |
1608 (goto-char beg) | |
1609 (insert header) | |
1610 (insert (format "Content-Type: %s\n" ctype)) | |
1611 (if encoding | |
1612 (insert (format "Content-Transfer-Encoding: %s\n" encoding)) | |
1613 ) | |
1614 (insert "\n") | |
1615 (or (funcall mime-editor/pgp-encrypt-function | |
1616 recipients (point-min) (point-max) from) | |
1617 (throw 'mime-editor/error 'pgp-error) | |
1618 ) | |
1619 (goto-char beg) | |
1620 (insert (format "--[[multipart/encrypted; | |
1621 boundary=\"%s\"; | |
1622 protocol=\"application/pgp-encrypted\"][7bit]] | |
1623 --%s | |
1624 Content-Type: application/pgp-encrypted | |
1625 | |
1626 --%s | |
1627 Content-Type: application/octet-stream | |
1628 Content-Transfer-Encoding: 7bit | |
1629 | |
1630 " pgp-boundary pgp-boundary pgp-boundary)) | |
1631 (goto-char (point-max)) | |
1632 (insert (format "\n--%s--\n" pgp-boundary)) | |
1633 ))))) | |
1634 | |
1635 (defun mime-editor/sign-pgp-kazu (beg end boundary) | |
1636 (save-excursion | |
1637 (save-restriction | |
1638 (narrow-to-region beg end) | |
1639 (let* ((ret | |
1640 (mime-editor/translate-region beg end boundary)) | |
1641 (ctype (car ret)) | |
1642 (encoding (nth 1 ret)) | |
1643 (parts (nth 3 ret)) | |
1644 ) | |
1645 (goto-char beg) | |
1646 (insert (format "Content-Type: %s\n" ctype)) | |
1647 (if encoding | |
1648 (insert (format "Content-Transfer-Encoding: %s\n" encoding)) | |
1649 ) | |
1650 (insert "\n") | |
1651 (or (as-binary-process | |
1652 (funcall mime-editor/traditional-pgp-sign-function | |
1653 beg (point-max))) | |
1654 (throw 'mime-editor/error 'pgp-error) | |
1655 ) | |
1656 (goto-char beg) | |
1657 (insert | |
1658 "--[[application/pgp; format=mime][7bit]]\n") | |
1659 )) | |
1660 )) | |
1661 | |
1662 (defun mime-editor/encrypt-pgp-kazu (beg end boundary) | |
1663 (save-excursion | |
1664 (let (from recipients header) | |
1665 (let ((ret (mime-editor/make-encrypt-recipient-header))) | |
1666 (setq from (aref ret 0) | |
1667 recipients (aref ret 1) | |
1668 header (aref ret 2)) | |
1669 ) | |
1670 (save-restriction | |
1671 (narrow-to-region beg end) | |
1672 (let* ((ret | |
1673 (mime-editor/translate-region beg end boundary)) | |
1674 (ctype (car ret)) | |
1675 (encoding (nth 1 ret)) | |
1676 (parts (nth 3 ret)) | |
1677 ) | |
1678 (goto-char beg) | |
1679 (insert header) | |
1680 (insert (format "Content-Type: %s\n" ctype)) | |
1681 (if encoding | |
1682 (insert (format "Content-Transfer-Encoding: %s\n" encoding)) | |
1683 ) | |
1684 (insert "\n") | |
1685 (or (as-binary-process | |
1686 (funcall mime-editor/pgp-encrypt-function | |
1687 recipients beg (point-max) nil 'maybe) | |
1688 ) | |
1689 (throw 'mime-editor/error 'pgp-error) | |
1690 ) | |
1691 (goto-char beg) | |
1692 (insert | |
1693 "--[[application/pgp; format=mime][7bit]]\n") | |
1694 )) | |
1695 ))) | |
1696 | |
1697 (defun mime-editor/translate-body () | |
1698 "Encode the tagged MIME body in current buffer in MIME compliant message." | |
1699 (interactive) | |
1700 (save-excursion | |
1701 (let ((boundary | |
1702 (concat mime-multipart-boundary "_" | |
1703 (replace-space-with-underline (current-time-string)) | |
1704 )) | |
1705 (i 1) | |
1706 ret) | |
1707 (while (mime-editor/process-multipart-1 | |
1708 (format "%s-%d" boundary i)) | |
1709 (setq i (1+ i)) | |
1710 ) | |
1711 (save-restriction | |
1712 ;; We are interested in message body. | |
1713 (let* ((beg | |
1714 (progn | |
1715 (goto-char (point-min)) | |
1716 (re-search-forward | |
1717 (concat "\n" (regexp-quote mail-header-separator) | |
1718 (if mime-ignore-preceding-spaces | |
1719 "[ \t\n]*\n" "\n")) nil 'move) | |
1720 (point))) | |
1721 (end | |
1722 (progn | |
1723 (goto-char (point-max)) | |
1724 (and mime-ignore-trailing-spaces | |
1725 (re-search-backward "[^ \t\n]\n" beg t) | |
1726 (forward-char 1)) | |
1727 (point)))) | |
1728 (setq ret (mime-editor/translate-region | |
1729 beg end | |
1730 (format "%s-%d" boundary i))) | |
1731 )) | |
1732 (mime-editor/dequote-region (point-min)(point-max)) | |
1733 (let ((contype (car ret)) ;Content-Type | |
1734 (encoding (nth 1 ret)) ;Content-Transfer-Encoding | |
1735 ) | |
1736 ;; Make primary MIME headers. | |
1737 (or (mail-position-on-field "Mime-Version") | |
1738 (insert mime-editor/mime-version-value)) | |
1739 ;; Remove old Content-Type and other fields. | |
1740 (save-restriction | |
1741 (goto-char (point-min)) | |
1742 (search-forward (concat "\n" mail-header-separator "\n") nil t) | |
1743 (narrow-to-region (point-min) (point)) | |
1744 (goto-char (point-min)) | |
1745 (mime-delete-field "Content-Type") | |
1746 (mime-delete-field "Content-Transfer-Encoding")) | |
1747 ;; Then, insert Content-Type and Content-Transfer-Encoding fields. | |
1748 (mail-position-on-field "Content-Type") | |
1749 (insert contype) | |
1750 (if encoding | |
1751 (progn | |
1752 (mail-position-on-field "Content-Transfer-Encoding") | |
1753 (insert encoding))) | |
1754 )))) | |
1755 | |
1756 (defun mime-editor/translate-single-part-tag (&optional prefix) | |
1757 (if (re-search-forward mime-editor/single-part-tag-regexp nil t) | |
1758 (let* ((beg (match-beginning 0)) | |
1759 (end (match-end 0)) | |
1760 (tag (buffer-substring beg end)) | |
1761 ) | |
1762 (delete-region beg end) | |
1763 (setq contype (mime-editor/get-contype tag)) | |
1764 (setq encoding (mime-editor/get-encoding tag)) | |
1765 (insert (concat prefix "--" boundary "\n")) | |
1766 (save-restriction | |
1767 (narrow-to-region (point)(point)) | |
1768 (insert "Content-Type: " contype "\n") | |
1769 (if encoding | |
1770 (insert "Content-Transfer-Encoding: " encoding "\n")) | |
1771 (mime/encode-message-header) | |
1772 ) | |
1773 t))) | |
1774 | |
1775 (defun mime-editor/translate-region (beg end &optional boundary multipart) | |
1776 (if (null boundary) | |
1777 (setq boundary | |
1778 (concat mime-multipart-boundary "_" | |
1779 (replace-space-with-underline (current-time-string)))) | |
1780 ) | |
1781 (save-excursion | |
1782 (save-restriction | |
1783 (narrow-to-region beg end) | |
1784 (let ((tag nil) ;MIME tag | |
1785 (contype nil) ;Content-Type | |
1786 (encoding nil) ;Content-Transfer-Encoding | |
1787 (nparts 0)) ;Number of body parts | |
1788 ;; Normalize the body part by inserting appropriate message | |
1789 ;; tags for every message contents. | |
1790 (mime-editor/normalize-body) | |
1791 ;; Counting the number of Content-Type. | |
1792 (goto-char (point-min)) | |
1793 (while (re-search-forward mime-editor/single-part-tag-regexp nil t) | |
1794 (setq nparts (1+ nparts))) | |
1795 ;; Begin translation. | |
1796 (cond | |
1797 ((and (<= nparts 1)(not multipart)) | |
1798 ;; It's a singular message. | |
1799 (goto-char (point-min)) | |
1800 (while (re-search-forward | |
1801 mime-editor/single-part-tag-regexp nil t) | |
1802 (setq tag | |
1803 (buffer-substring (match-beginning 0) (match-end 0))) | |
1804 (delete-region (match-beginning 0) (1+ (match-end 0))) | |
1805 (setq contype (mime-editor/get-contype tag)) | |
1806 (setq encoding (mime-editor/get-encoding tag)) | |
1807 )) | |
1808 (t | |
1809 ;; It's a multipart message. | |
1810 (goto-char (point-min)) | |
1811 (and (mime-editor/translate-single-part-tag) | |
1812 (while (mime-editor/translate-single-part-tag "\n")) | |
1813 ) | |
1814 ;; Define Content-Type as "multipart/mixed". | |
1815 (setq contype | |
1816 (concat "multipart/mixed;\n boundary=\"" boundary "\"")) | |
1817 ;; Content-Transfer-Encoding must be "7bit". | |
1818 ;; The following encoding can be `nil', but is | |
1819 ;; specified as is since there is no way that a user | |
1820 ;; specifies it. | |
1821 (setq encoding "7bit") | |
1822 ;; Insert the trailer. | |
1823 (goto-char (point-max)) | |
1824 (insert "\n--" boundary "--\n") | |
1825 )) | |
1826 (list contype encoding boundary nparts) | |
1827 )))) | |
1828 | |
1829 (defun mime-editor/normalize-body () | |
1830 "Normalize the body part by inserting appropriate message tags." | |
1831 ;; Insert the first MIME tags if necessary. | |
1832 (goto-char (point-min)) | |
1833 (if (not (looking-at mime-editor/single-part-tag-regexp)) | |
1834 (insert (mime-make-text-tag) "\n")) | |
1835 ;; Check each tag, and add new tag or correct it if necessary. | |
1836 (goto-char (point-min)) | |
1837 (while (re-search-forward mime-editor/single-part-tag-regexp nil t) | |
1838 (let* ((tag (buffer-substring (match-beginning 0) (match-end 0))) | |
1839 (contype (mime-editor/get-contype tag)) | |
1840 (charset (mime-get-parameter contype "charset")) | |
1841 (encoding (mime-editor/get-encoding tag))) | |
1842 ;; Remove extra whitespaces after the tag. | |
1843 (if (looking-at "[ \t]+$") | |
1844 (delete-region (match-beginning 0) (match-end 0))) | |
1845 (let ((beg (point)) | |
1846 (end (mime-editor/content-end)) | |
1847 ) | |
1848 (if (= end (point-max)) | |
1849 nil | |
1850 (goto-char end) | |
1851 (or (looking-at mime-editor/beginning-tag-regexp) | |
1852 (eobp) | |
1853 (insert (mime-make-text-tag) "\n") | |
1854 )) | |
1855 (visible-region beg end) | |
1856 (goto-char beg) | |
1857 ) | |
1858 (cond | |
1859 ((mime-test-content-type contype "message") | |
1860 ;; Content-type "message" should be sent as is. | |
1861 (forward-line 1) | |
1862 ) | |
1863 ((mime-test-content-type contype "text") | |
1864 ;; Define charset for text if necessary. | |
1865 (setq charset (if charset | |
1866 (intern (downcase charset)) | |
1867 (mime-editor/choose-charset))) | |
1868 (mime-editor/define-charset charset) | |
1869 (cond ((string-equal contype "text/x-rot13-47") | |
1870 (save-excursion | |
1871 (forward-line) | |
1872 (set-mark (point)) | |
1873 (goto-char (mime-editor/content-end)) | |
1874 (tm:caesar-region) | |
1875 )) | |
1876 ((string-equal contype "text/enriched") | |
1877 (save-excursion | |
1878 (let ((beg (progn | |
1879 (forward-line) | |
1880 (point))) | |
1881 (end (mime-editor/content-end)) | |
1882 ) | |
1883 ;; Patch for hard newlines | |
1884 ;; (save-excursion | |
1885 ;; (goto-char beg) | |
1886 ;; (while (search-forward "\n" end t) | |
1887 ;; (put-text-property (match-beginning 0) | |
1888 ;; (point) | |
1889 ;; 'hard t))) | |
1890 ;; End patch for hard newlines | |
1891 (enriched-encode beg end) | |
1892 (goto-char beg) | |
1893 (if (search-forward "\n\n") | |
1894 (delete-region beg (match-end 0)) | |
1895 ) | |
1896 )))) | |
1897 ;; Point is now on current tag. | |
1898 ;; Define encoding and encode text if necessary. | |
1899 (or encoding ;Encoding is not specified. | |
1900 (let* ((encoding | |
1901 (cdr | |
1902 (assq charset | |
1903 mime-editor/charset-default-encoding-alist) | |
1904 )) | |
1905 (beg (mime-editor/content-beginning)) | |
1906 ) | |
1907 (encode-mime-charset-region beg (mime-editor/content-end) | |
1908 charset) | |
1909 (mime-encode-region beg (mime-editor/content-end) encoding) | |
1910 (mime-editor/define-encoding encoding) | |
1911 )) | |
1912 (goto-char (mime-editor/content-end)) | |
1913 ) | |
1914 ((null encoding) ;Encoding is not specified. | |
1915 ;; Application, image, audio, video, and any other | |
1916 ;; unknown content-type without encoding should be | |
1917 ;; encoded. | |
1918 (let* ((encoding "base64") ;Encode in BASE64 by default. | |
1919 (beg (mime-editor/content-beginning)) | |
1920 (end (mime-editor/content-end)) | |
1921 (body (buffer-substring beg end)) | |
1922 ) | |
1923 (mime-encode-region beg end encoding) | |
1924 (mime-editor/define-encoding encoding)) | |
1925 (forward-line 1) | |
1926 )) | |
1927 ))) | |
1928 | |
1929 (defun mime-delete-field (field) | |
1930 "Delete header FIELD." | |
1931 (let ((regexp (format "^%s:[ \t]*" field))) | |
1932 (goto-char (point-min)) | |
1933 (while (re-search-forward regexp nil t) | |
1934 (delete-region (match-beginning 0) | |
1935 (progn (forward-line 1) (point))) | |
1936 ))) | |
1937 | |
1938 | |
1939 ;;; | |
1940 ;;; Platform dependent functions | |
1941 ;;; | |
1942 | |
1943 ;; Sun implementations | |
1944 | |
1945 (defun mime-editor/voice-recorder-for-sun (encoding) | |
1946 "Record voice in a buffer using Sun audio device, | |
1947 and insert data encoded as ENCODING. [tm-edit.el]" | |
1948 (message "Start the recording on %s. Type C-g to finish the recording..." | |
1949 (system-name)) | |
1950 (mime-insert-encoded-file "/dev/audio" encoding) | |
1951 ) | |
1952 | |
1953 | |
1954 ;;; @ Other useful commands. | |
1955 ;;; | |
1956 | |
1957 ;; Message forwarding commands as content-type "message/rfc822". | |
1958 | |
1959 (defun mime-editor/insert-message (&optional message) | |
1960 (interactive) | |
1961 (let ((inserter (assoc-value major-mode mime-editor/message-inserter-alist))) | |
1962 (if (and inserter (fboundp inserter)) | |
1963 (progn | |
1964 (mime-editor/insert-tag "message" "rfc822") | |
1965 (funcall inserter message) | |
1966 ) | |
1967 (message "Sorry, I don't have message inserter for your MUA.") | |
1968 ))) | |
1969 | |
1970 (defun mime-editor/insert-mail (&optional message) | |
1971 (interactive) | |
1972 (let ((inserter (assoc-value major-mode mime-editor/mail-inserter-alist))) | |
1973 (if (and inserter (fboundp inserter)) | |
1974 (progn | |
1975 (mime-editor/insert-tag "message" "rfc822") | |
1976 (funcall inserter message) | |
1977 ) | |
1978 (message "Sorry, I don't have mail inserter for your MUA.") | |
1979 ))) | |
1980 | |
1981 (defun mime-editor/inserted-message-filter () | |
1982 (save-excursion | |
1983 (save-restriction | |
1984 (let ((header-start (point)) | |
1985 (case-fold-search t) | |
1986 beg end) | |
1987 ;; for Emacs 18 | |
1988 ;; (if (re-search-forward "^$" (marker-position (mark-marker))) | |
1989 (if (re-search-forward "^$" (mark t)) | |
1990 (narrow-to-region header-start (match-beginning 0)) | |
1991 ) | |
1992 (goto-char header-start) | |
1993 (while (and (re-search-forward | |
1994 mime-editor/yank-ignored-field-regexp nil t) | |
1995 (setq beg (match-beginning 0)) | |
1996 (setq end (1+ (std11-field-end))) | |
1997 ) | |
1998 (delete-region beg end) | |
1999 ) | |
2000 )))) | |
2001 | |
2002 | |
2003 ;;; @ multipart enclosure | |
2004 ;;; | |
2005 | |
2006 (defun mime-editor/enclose-region (type beg end) | |
2007 (save-excursion | |
2008 (goto-char beg) | |
2009 (let ((current (point))) | |
2010 (save-restriction | |
2011 (narrow-to-region beg end) | |
2012 (insert (format "--<<%s>>-{\n" type)) | |
2013 (goto-char (point-max)) | |
2014 (insert (format "--}-<<%s>>\n" type)) | |
2015 (goto-char (point-max)) | |
2016 ) | |
2017 (or (looking-at mime-editor/beginning-tag-regexp) | |
2018 (eobp) | |
2019 (insert (mime-make-text-tag) "\n") | |
2020 ) | |
2021 ))) | |
2022 | |
2023 (defun mime-editor/enclose-quote-region (beg end) | |
2024 (interactive "*r") | |
2025 (mime-editor/enclose-region "quote" beg end) | |
2026 ) | |
2027 | |
2028 (defun mime-editor/enclose-mixed-region (beg end) | |
2029 (interactive "*r") | |
2030 (mime-editor/enclose-region "mixed" beg end) | |
2031 ) | |
2032 | |
2033 (defun mime-editor/enclose-parallel-region (beg end) | |
2034 (interactive "*r") | |
2035 (mime-editor/enclose-region "parallel" beg end) | |
2036 ) | |
2037 | |
2038 (defun mime-editor/enclose-digest-region (beg end) | |
2039 (interactive "*r") | |
2040 (mime-editor/enclose-region "digest" beg end) | |
2041 ) | |
2042 | |
2043 (defun mime-editor/enclose-alternative-region (beg end) | |
2044 (interactive "*r") | |
2045 (mime-editor/enclose-region "alternative" beg end) | |
2046 ) | |
2047 | |
2048 (defun mime-editor/enclose-signed-region (beg end) | |
2049 (interactive "*r") | |
2050 (if mime-editor/signing-type | |
2051 (mime-editor/enclose-region "signed" beg end) | |
2052 (message "Please specify signing type.") | |
2053 )) | |
2054 | |
2055 (defun mime-editor/enclose-encrypted-region (beg end) | |
2056 (interactive "*r") | |
2057 (if mime-editor/signing-type | |
2058 (mime-editor/enclose-region "encrypted" beg end) | |
2059 (message "Please specify encrypting type.") | |
2060 )) | |
2061 | |
2062 (defun mime-editor/insert-key (&optional arg) | |
2063 "Insert a pgp public key." | |
2064 (interactive "P") | |
2065 (mime-editor/insert-tag "application" "pgp-keys") | |
2066 (mime-editor/define-encoding "7bit") | |
2067 (funcall mime-editor/pgp-insert-public-key-function) | |
2068 ) | |
2069 | |
2070 | |
2071 ;;; @ flag setting | |
2072 ;;; | |
2073 | |
2074 (defun mime-editor/set-split (arg) | |
2075 (interactive | |
2076 (list | |
2077 (y-or-n-p "Do you want to enable split?") | |
2078 )) | |
2079 (setq mime-editor/split-message arg) | |
2080 (if arg | |
2081 (message "This message is enabled to split.") | |
2082 (message "This message is not enabled to split.") | |
2083 )) | |
2084 | |
2085 (defun mime-editor/toggle-transfer-level (&optional transfer-level) | |
2086 "Toggle transfer-level is 7bit or 8bit through. | |
2087 | |
2088 Optional TRANSFER-LEVEL is a number of transfer-level, 7 or 8." | |
2089 (interactive) | |
2090 (if (numberp transfer-level) | |
2091 (setq mime-editor/transfer-level transfer-level) | |
2092 (if (< mime-editor/transfer-level 8) | |
2093 (setq mime-editor/transfer-level 8) | |
2094 (setq mime-editor/transfer-level 7) | |
2095 )) | |
2096 (setq mime-editor/charset-default-encoding-alist | |
2097 (mime-editor/make-charset-default-encoding-alist | |
2098 mime-editor/transfer-level)) | |
2099 (message (format "Current transfer-level is %d bit" | |
2100 mime-editor/transfer-level)) | |
2101 (setq mime-editor/transfer-level-string | |
2102 (mime/encoding-name mime-editor/transfer-level 'not-omit)) | |
2103 (force-mode-line-update) | |
2104 ) | |
2105 | |
2106 (defun mime-editor/set-transfer-level-7bit () | |
2107 (interactive) | |
2108 (mime-editor/toggle-transfer-level 7) | |
2109 ) | |
2110 | |
2111 (defun mime-editor/set-transfer-level-8bit () | |
2112 (interactive) | |
2113 (mime-editor/toggle-transfer-level 8) | |
2114 ) | |
2115 | |
2116 | |
2117 ;;; @ pgp | |
2118 ;;; | |
2119 | |
2120 (defun mime-editor/set-sign (arg) | |
2121 (interactive | |
2122 (list | |
2123 (y-or-n-p "Do you want to sign?") | |
2124 )) | |
2125 (if arg | |
2126 (if mime-editor/signing-type | |
2127 (progn | |
2128 (setq mime-editor/pgp-processing 'sign) | |
2129 (message "This message will be signed.") | |
2130 ) | |
2131 (message "Please specify signing type.") | |
2132 ) | |
2133 (if (eq mime-editor/pgp-processing 'sign) | |
2134 (setq mime-editor/pgp-processing nil) | |
2135 ) | |
2136 (message "This message will not be signed.") | |
2137 )) | |
2138 | |
2139 (defun mime-editor/set-encrypt (arg) | |
2140 (interactive | |
2141 (list | |
2142 (y-or-n-p "Do you want to encrypt?") | |
2143 )) | |
2144 (if arg | |
2145 (if mime-editor/encrypting-type | |
2146 (progn | |
2147 (setq mime-editor/pgp-processing 'encrypt) | |
2148 (message "This message will be encrypt.") | |
2149 ) | |
2150 (message "Please specify encrypting type.") | |
2151 ) | |
2152 (if (eq mime-editor/pgp-processing 'encrypt) | |
2153 (setq mime-editor/pgp-processing nil) | |
2154 ) | |
2155 (message "This message will not be encrypt.") | |
2156 )) | |
2157 | |
2158 (defvar mime-editor/pgp-processing nil) | |
2159 (make-variable-buffer-local 'mime-editor/pgp-processing) | |
2160 | |
2161 (defun mime-editor/pgp-enclose-buffer () | |
2162 (let ((beg (save-excursion | |
2163 (goto-char (point-min)) | |
2164 (if (search-forward (concat "\n" mail-header-separator "\n")) | |
2165 (match-end 0) | |
2166 ))) | |
2167 (end (point-max)) | |
2168 ) | |
2169 (if beg | |
2170 (cond ((eq mime-editor/pgp-processing 'sign) | |
2171 (mime-editor/enclose-signed-region beg end) | |
2172 ) | |
2173 ((eq mime-editor/pgp-processing 'encrypt) | |
2174 (mime-editor/enclose-encrypted-region beg end) | |
2175 )) | |
2176 ))) | |
2177 | |
2178 | |
2179 ;;; @ split | |
2180 ;;; | |
2181 | |
2182 (defun mime-editor/insert-partial-header | |
2183 (fields subject id number total separator) | |
2184 (insert fields) | |
2185 (insert (format "Subject: %s (%d/%d)\n" subject number total)) | |
2186 (insert (format "Mime-Version: 1.0 (split by %s)\n" | |
2187 mime-editor/version-name)) | |
2188 (insert (format "\ | |
2189 Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n" | |
2190 id number total separator)) | |
2191 ) | |
2192 | |
2193 (defun mime-editor/split-and-send | |
2194 (&optional cmd lines mime-editor/message-max-length) | |
2195 (interactive) | |
2196 (or lines | |
2197 (setq lines | |
2198 (count-lines (point-min) (point-max))) | |
2199 ) | |
2200 (or mime-editor/message-max-length | |
2201 (setq mime-editor/message-max-length | |
2202 (or (cdr (assq major-mode mime-editor/message-max-lines-alist)) | |
2203 mime-editor/message-default-max-lines)) | |
2204 ) | |
2205 (let* ((mime-editor/draft-file-name | |
2206 (or (buffer-file-name) | |
2207 (make-temp-name | |
2208 (expand-file-name "tm-draft" mime/tmp-dir)))) | |
2209 (separator mail-header-separator) | |
2210 (id (concat "\"" | |
2211 (replace-space-with-underline (current-time-string)) | |
2212 "@" (system-name) "\""))) | |
2213 (run-hooks 'mime-editor/before-split-hook) | |
2214 (let ((the-buf (current-buffer)) | |
2215 (copy-buf (get-buffer-create " *Original Message*")) | |
2216 (header (std11-header-string-except | |
2217 mime-editor/split-ignored-field-regexp separator)) | |
2218 (subject (mail-fetch-field "subject")) | |
2219 (total (+ (/ lines mime-editor/message-max-length) | |
2220 (if (> (mod lines mime-editor/message-max-length) 0) | |
2221 1))) | |
2222 (command | |
2223 (or cmd | |
2224 (cdr | |
2225 (assq major-mode | |
2226 mime-editor/split-message-sender-alist)) | |
2227 (function | |
2228 (lambda () | |
2229 (interactive) | |
2230 (error "Split sender is not specified for `%s'." major-mode) | |
2231 )) | |
2232 )) | |
2233 (mime-editor/partial-number 1) | |
2234 data) | |
2235 (save-excursion | |
2236 (set-buffer copy-buf) | |
2237 (erase-buffer) | |
2238 (insert-buffer the-buf) | |
2239 (save-restriction | |
2240 (if (re-search-forward | |
2241 (concat "^" (regexp-quote separator) "$") nil t) | |
2242 (let ((he (match-beginning 0))) | |
2243 (replace-match "") | |
2244 (narrow-to-region (point-min) he) | |
2245 )) | |
2246 (goto-char (point-min)) | |
2247 (while (re-search-forward mime-editor/split-blind-field-regexp nil t) | |
2248 (delete-region (match-beginning 0) | |
2249 (1+ (std11-field-end))) | |
2250 ))) | |
2251 (while (< mime-editor/partial-number total) | |
2252 (erase-buffer) | |
2253 (save-excursion | |
2254 (set-buffer copy-buf) | |
2255 (setq data (buffer-substring | |
2256 (point-min) | |
2257 (progn | |
2258 (goto-line mime-editor/message-max-length) | |
2259 (point)) | |
2260 )) | |
2261 (delete-region (point-min)(point)) | |
2262 ) | |
2263 (mime-editor/insert-partial-header | |
2264 header subject id mime-editor/partial-number total separator) | |
2265 (insert data) | |
2266 (save-excursion | |
2267 (message (format "Sending %d/%d..." | |
2268 mime-editor/partial-number total)) | |
2269 (call-interactively command) | |
2270 (message (format "Sending %d/%d... done" | |
2271 mime-editor/partial-number total)) | |
2272 ) | |
2273 (setq mime-editor/partial-number | |
2274 (1+ mime-editor/partial-number)) | |
2275 ) | |
2276 (erase-buffer) | |
2277 (save-excursion | |
2278 (set-buffer copy-buf) | |
2279 (setq data (buffer-string)) | |
2280 (erase-buffer) | |
2281 ) | |
2282 (mime-editor/insert-partial-header | |
2283 header subject id mime-editor/partial-number total separator) | |
2284 (insert data) | |
2285 (save-excursion | |
2286 (message (format "Sending %d/%d..." | |
2287 mime-editor/partial-number total)) | |
2288 (message (format "Sending %d/%d... done" | |
2289 mime-editor/partial-number total)) | |
2290 ) | |
2291 ))) | |
2292 | |
2293 (defun mime-editor/maybe-split-and-send (&optional cmd) | |
2294 (interactive) | |
2295 (run-hooks 'mime-editor/before-send-hook) | |
2296 (let ((mime-editor/message-max-length | |
2297 (or (cdr (assq major-mode mime-editor/message-max-lines-alist)) | |
2298 mime-editor/message-default-max-lines)) | |
2299 (lines (count-lines (point-min) (point-max))) | |
2300 ) | |
2301 (if (and (> lines mime-editor/message-max-length) | |
2302 mime-editor/split-message) | |
2303 (mime-editor/split-and-send cmd lines mime-editor/message-max-length) | |
2304 ))) | |
2305 | |
2306 | |
2307 ;;; @ preview message | |
2308 ;;; | |
2309 | |
2310 (defun mime-editor/preview-message () | |
2311 "preview editing MIME message. [tm-edit.el]" | |
2312 (interactive) | |
2313 (let* ((str (buffer-string)) | |
2314 (separator mail-header-separator) | |
2315 (the-buf (current-buffer)) | |
2316 (buf-name (buffer-name)) | |
2317 (temp-buf-name (concat "*temp-article:" buf-name "*")) | |
2318 (buf (get-buffer temp-buf-name)) | |
2319 ) | |
2320 (if buf | |
2321 (progn | |
2322 (switch-to-buffer buf) | |
2323 (erase-buffer) | |
2324 ) | |
2325 (setq buf (get-buffer-create temp-buf-name)) | |
2326 (switch-to-buffer buf) | |
2327 ) | |
2328 (insert str) | |
2329 (setq major-mode 'mime/temporary-message-mode) | |
2330 (make-local-variable 'mail-header-separator) | |
2331 (setq mail-header-separator separator) | |
2332 (make-local-variable 'mime/editing-buffer) | |
2333 (setq mime/editing-buffer the-buf) | |
2334 | |
2335 (run-hooks 'mime-editor/translate-hook) | |
2336 (mime-editor/translate-buffer) | |
2337 (goto-char (point-min)) | |
2338 (if (re-search-forward | |
2339 (concat "^" (regexp-quote separator) "$")) | |
2340 (replace-match "") | |
2341 ) | |
2342 (mime/viewer-mode) | |
2343 )) | |
2344 | |
2345 (defun mime-editor/quitting-method () | |
2346 (let ((temp mime::preview/article-buffer) | |
2347 buf) | |
2348 (mime-viewer/kill-buffer) | |
2349 (set-buffer temp) | |
2350 (setq buf mime/editing-buffer) | |
2351 (kill-buffer temp) | |
2352 (switch-to-buffer buf) | |
2353 )) | |
2354 | |
2355 (set-alist 'mime-viewer/quitting-method-alist | |
2356 'mime/temporary-message-mode | |
2357 (function mime-editor/quitting-method) | |
2358 ) | |
2359 | |
2360 | |
2361 ;;; @ draft preview | |
2362 ;;; | |
2363 ;; by "OKABE Yasuo <okabe@kudpc.kyoto-u.ac.jp> | |
2364 ;; Mon, 10 Apr 1995 20:03:07 +0900 | |
2365 | |
2366 (defvar mime-editor/draft-header-separator-alist | |
2367 '((news-reply-mode . mail-header-separator) | |
2368 (mh-letter-mode . mail-header-separator) | |
2369 )) | |
2370 | |
2371 (defvar mime::article/draft-header-separator nil) | |
2372 | |
2373 (defun mime-editor/draft-preview () | |
2374 (interactive) | |
2375 (let ((sep (cdr (assq major-mode mime-editor/draft-header-separator-alist)))) | |
2376 (or (stringp sep) (setq sep (eval sep))) | |
2377 (make-variable-buffer-local 'mime::article/draft-header-separator) | |
2378 (goto-char (point-min)) | |
2379 (re-search-forward | |
2380 (concat "^\\(" (regexp-quote sep) "\\)?$")) | |
2381 (setq mime::article/draft-header-separator | |
2382 (buffer-substring (match-beginning 0) (match-end 0))) | |
2383 (replace-match "") | |
2384 (mime/viewer-mode (current-buffer)) | |
2385 (pop-to-buffer (current-buffer)) | |
2386 )) | |
2387 | |
2388 (defun mime-viewer::quitting-method/draft-preview () | |
2389 (let ((mother mime::preview/mother-buffer)) | |
2390 (save-excursion | |
2391 (switch-to-buffer mother) | |
2392 (goto-char (point-min)) | |
2393 (if (and | |
2394 (re-search-forward | |
2395 (concat "^\\(" | |
2396 (regexp-quote mime::article/draft-header-separator) | |
2397 "\\)?$") nil t) | |
2398 (bolp)) | |
2399 (progn | |
2400 (insert mime::article/draft-header-separator) | |
2401 (set-buffer-modified-p (buffer-modified-p)) | |
2402 ))) | |
2403 (mime-viewer/kill-buffer) | |
2404 (pop-to-buffer mother) | |
2405 )) | |
2406 | |
2407 (set-alist 'mime-viewer/quitting-method-alist | |
2408 'mh-letter-mode | |
2409 (function mime-viewer::quitting-method/draft-preview) | |
2410 ) | |
2411 | |
2412 (set-alist 'mime-viewer/quitting-method-alist | |
2413 'news-reply-mode | |
2414 (function mime-viewer::quitting-method/draft-preview) | |
2415 ) | |
2416 | |
2417 | |
2418 ;;; @ edit again | |
2419 ;;; | |
2420 | |
2421 (defun mime-editor::edit-again (code-conversion) | |
2422 (save-excursion | |
2423 (goto-char (point-min)) | |
2424 (let ((ctl (mime/Content-Type))) | |
2425 (if ctl | |
2426 (let ((ctype (car ctl)) | |
2427 (params (cdr ctl)) | |
2428 type stype) | |
2429 (if (string-match "/" ctype) | |
2430 (progn | |
2431 (setq type (substring ctype 0 (match-beginning 0))) | |
2432 (setq stype (substring ctype (match-end 0))) | |
2433 ) | |
2434 (setq type ctype) | |
2435 ) | |
2436 (cond | |
2437 ((string-equal type "multipart") | |
2438 (let* ((boundary (assoc-value "boundary" params)) | |
2439 (boundary-pat | |
2440 (concat "\n--" (regexp-quote boundary) "[ \t]*\n")) | |
2441 ) | |
2442 (re-search-forward boundary-pat nil t) | |
2443 (let ((bb (match-beginning 0)) eb tag) | |
2444 (setq tag (format "\n--<<%s>>-{\n" stype)) | |
2445 (goto-char bb) | |
2446 (insert tag) | |
2447 (setq bb (+ bb (length tag))) | |
2448 (re-search-forward | |
2449 (concat "\n--" (regexp-quote boundary) "--[ \t]*\n") | |
2450 nil t) | |
2451 (setq eb (match-beginning 0)) | |
2452 (replace-match (format "--}-<<%s>>\n" stype)) | |
2453 (save-restriction | |
2454 (narrow-to-region bb eb) | |
2455 (goto-char (point-min)) | |
2456 (while (re-search-forward boundary-pat nil t) | |
2457 (let ((beg (match-beginning 0)) | |
2458 end) | |
2459 (delete-region beg (match-end 0)) | |
2460 (save-excursion | |
2461 (if (re-search-forward boundary-pat nil t) | |
2462 (setq end (match-beginning 0)) | |
2463 (setq end (point-max)) | |
2464 ) | |
2465 (save-restriction | |
2466 (narrow-to-region beg end) | |
2467 (mime-editor::edit-again code-conversion) | |
2468 (goto-char (point-max)) | |
2469 )))) | |
2470 )) | |
2471 (goto-char (point-min)) | |
2472 (or (= (point-min) 1) | |
2473 (delete-region (point-min) | |
2474 (if (search-forward "\n\n" nil t) | |
2475 (match-end 0) | |
2476 (point-min) | |
2477 ))) | |
2478 )) | |
2479 (t | |
2480 (let* (charset | |
2481 (pstr | |
2482 (mapconcat (function | |
2483 (lambda (attr) | |
2484 (if (string-equal (car attr) | |
2485 "charset") | |
2486 (progn | |
2487 (setq charset (cdr attr)) | |
2488 "") | |
2489 (concat ";" (car attr) | |
2490 "=" (cdr attr)) | |
2491 ) | |
2492 )) | |
2493 params "")) | |
2494 encoding | |
2495 encoded) | |
2496 (save-excursion | |
2497 (if (re-search-forward | |
2498 "Content-Transfer-Encoding:" nil t) | |
2499 (let ((beg (match-beginning 0)) | |
2500 (hbeg (match-end 0)) | |
2501 (end (std11-field-end))) | |
2502 (setq encoding | |
2503 (eliminate-top-spaces | |
2504 (std11-unfold-string | |
2505 (buffer-substring hbeg end)))) | |
2506 (if (or charset (string-equal type "text")) | |
2507 (progn | |
2508 (delete-region beg (1+ end)) | |
2509 (goto-char (point-min)) | |
2510 (if (search-forward "\n\n" nil t) | |
2511 (progn | |
2512 (mime-decode-region | |
2513 (match-end 0)(point-max) encoding) | |
2514 (setq encoded t | |
2515 encoding nil) | |
2516 ))))))) | |
2517 (if (or code-conversion encoded) | |
2518 (decode-mime-charset-region | |
2519 (point-min)(point-max) | |
2520 (or charset default-mime-charset)) | |
2521 ) | |
2522 (let ((he | |
2523 (if (re-search-forward "^$" nil t) | |
2524 (match-end 0) | |
2525 (point-min) | |
2526 ))) | |
2527 (if (= (point-min) 1) | |
2528 (progn | |
2529 (goto-char he) | |
2530 (insert | |
2531 (concat "\n" | |
2532 (mime-create-tag | |
2533 (concat type "/" stype pstr) encoding))) | |
2534 ) | |
2535 (delete-region (point-min) he) | |
2536 (insert | |
2537 (mime-create-tag | |
2538 (concat type "/" stype pstr) encoding)) | |
2539 )) | |
2540 )))) | |
2541 (if code-conversion | |
2542 (decode-mime-charset-region (point-min) (point-max) | |
2543 default-mime-charset) | |
2544 ) | |
2545 )))) | |
2546 | |
2547 (defun mime/edit-again (&optional code-conversion no-separator no-mode) | |
2548 (interactive) | |
2549 (mime-editor::edit-again code-conversion) | |
2550 (goto-char (point-min)) | |
2551 (save-restriction | |
2552 (narrow-to-region | |
2553 (point-min) | |
2554 (if (re-search-forward | |
2555 (concat "^\\(" (regexp-quote mail-header-separator) "\\)?$") | |
2556 nil t) | |
2557 (match-end 0) | |
2558 (point-max) | |
2559 )) | |
2560 (goto-char (point-min)) | |
2561 (while (re-search-forward | |
2562 "^\\(Content-.*\\|Mime-Version\\):" nil t) | |
2563 (delete-region (match-beginning 0) (1+ (std11-field-end))) | |
2564 )) | |
2565 (or no-separator | |
2566 (and (re-search-forward "^$") | |
2567 (replace-match mail-header-separator) | |
2568 )) | |
2569 (or no-mode | |
2570 (mime/editor-mode) | |
2571 )) | |
2572 | |
2573 | |
2574 ;;; @ end | |
2575 ;;; | |
2576 | |
2577 (provide 'tm-edit) | |
2578 | |
2579 (run-hooks 'tm-edit-load-hook) | |
2580 | |
2581 ;;; tm-edit.el ends here |