Mercurial > hg > xemacs-beta
comparison lisp/tm/tm-view.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-view.el --- interactive MIME viewer for GNU Emacs | |
2 | |
3 ;; Copyright (C) 1995,1996 Free Software Foundation, Inc. | |
4 | |
5 ;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp> | |
6 ;; Created: 1994/7/13 (1994/8/31 obsolete tm-body.el) | |
7 ;; Version: $Revision: 1.1.1.1 $ | |
8 ;; Keywords: mail, news, MIME, multimedia | |
9 | |
10 ;; This file is part of tm (Tools for MIME). | |
11 | |
12 ;; This program is free software; you can redistribute it and/or | |
13 ;; modify it under the terms of the GNU General Public License as | |
14 ;; published by the Free Software Foundation; either version 2, or (at | |
15 ;; your option) any later version. | |
16 | |
17 ;; This program is distributed in the hope that it will be useful, but | |
18 ;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
20 ;; General Public License for more details. | |
21 | |
22 ;; You should have received a copy of the GNU General Public License | |
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the | |
24 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
25 ;; Boston, MA 02111-1307, USA. | |
26 | |
27 ;;; Code: | |
28 | |
29 (require 'tl-str) | |
30 (require 'tl-list) | |
31 (require 'tl-atype) | |
32 (require 'tl-misc) | |
33 (require 'std11) | |
34 (require 'mel) | |
35 (require 'tm-ew-d) | |
36 (require 'tm-def) | |
37 (require 'tm-parse) | |
38 (require 'tm-text) | |
39 | |
40 | |
41 ;;; @ version | |
42 ;;; | |
43 | |
44 (defconst mime-viewer/RCS-ID | |
45 "$Id: tm-view.el,v 1.1.1.1 1996/12/18 03:55:32 steve Exp $") | |
46 | |
47 (defconst mime-viewer/version (get-version-string mime-viewer/RCS-ID)) | |
48 (defconst mime/viewer-version mime-viewer/version) | |
49 | |
50 | |
51 ;;; @ variables | |
52 ;;; | |
53 | |
54 (defvar mime/content-decoding-condition | |
55 '(((type . "text/plain") | |
56 (method "tm-plain" nil 'file 'type 'encoding 'mode 'name) | |
57 (mode "play" "print") | |
58 ) | |
59 ((type . "text/html") | |
60 (method "tm-html" nil 'file 'type 'encoding 'mode 'name) | |
61 (mode . "play") | |
62 ) | |
63 ((type . "text/x-rot13-47") | |
64 (method . mime-article/decode-caesar) | |
65 (mode . "play") | |
66 ) | |
67 ((type . "audio/basic") | |
68 (method "tm-au" nil 'file 'type 'encoding 'mode 'name) | |
69 (mode . "play") | |
70 ) | |
71 | |
72 ((type . "image/jpeg") | |
73 (method "tm-image" nil 'file 'type 'encoding 'mode 'name) | |
74 (mode "play" "print") | |
75 ) | |
76 ((type . "image/gif") | |
77 (method "tm-image" nil 'file 'type 'encoding 'mode 'name) | |
78 (mode "play" "print") | |
79 ) | |
80 ((type . "image/tiff") | |
81 (method "tm-image" nil 'file 'type 'encoding 'mode 'name) | |
82 (mode "play" "print") | |
83 ) | |
84 ((type . "image/x-tiff") | |
85 (method "tm-image" nil 'file 'type 'encoding 'mode 'name) | |
86 (mode "play" "print") | |
87 ) | |
88 ((type . "image/x-xbm") | |
89 (method "tm-image" nil 'file 'type 'encoding 'mode 'name) | |
90 (mode "play" "print") | |
91 ) | |
92 ((type . "image/x-pic") | |
93 (method "tm-image" nil 'file 'type 'encoding 'mode 'name) | |
94 (mode "play" "print") | |
95 ) | |
96 ((type . "image/x-mag") | |
97 (method "tm-image" nil 'file 'type 'encoding 'mode 'name) | |
98 (mode "play" "print") | |
99 ) | |
100 | |
101 ((type . "video/mpeg") | |
102 (method "tm-mpeg" nil 'file 'type 'encoding 'mode 'name) | |
103 (mode . "play") | |
104 ) | |
105 | |
106 ((type . "application/postscript") | |
107 (method "tm-ps" nil 'file 'type 'encoding 'mode 'name) | |
108 (mode "play" "print") | |
109 ) | |
110 ((type . "application/octet-stream") | |
111 (method "tm-file" nil 'file 'type 'encoding 'mode 'name) | |
112 (mode "play" "print") | |
113 ) | |
114 | |
115 ;;((type . "message/external-body") | |
116 ;; (method "xterm" nil | |
117 ;; "-e" "showexternal" | |
118 ;; 'file '"access-type" '"name" '"site" '"directory")) | |
119 ((type . "message/rfc822") | |
120 (method . mime-article/view-message/rfc822) | |
121 (mode . "play") | |
122 ) | |
123 ((type . "message/partial") | |
124 (method . mime-article/decode-message/partial) | |
125 (mode . "play") | |
126 ) | |
127 | |
128 ((method "metamail" t "-m" "tm" "-x" "-d" "-z" "-e" 'file) | |
129 (mode . "play") | |
130 ) | |
131 ((method "tm-file" nil 'file 'type 'encoding 'mode 'name) | |
132 (mode . "extract") | |
133 ) | |
134 )) | |
135 | |
136 (defvar mime-viewer/childrens-header-showing-Content-Type-list | |
137 '("message/rfc822" "message/news")) | |
138 | |
139 (defvar mime-viewer/default-showing-Content-Type-list | |
140 '("text/plain" nil "text/richtext" "text/enriched" | |
141 "text/x-latex" "application/x-latex" | |
142 "message/delivery-status" | |
143 "application/pgp" "text/x-pgp" | |
144 "application/octet-stream" | |
145 "application/x-selection" "application/x-comment")) | |
146 | |
147 (defvar mime-viewer/content-button-ignored-ctype-list | |
148 '("application/x-selection")) | |
149 | |
150 (defvar mime-viewer/content-button-visible-ctype-list | |
151 '("application/pgp")) | |
152 | |
153 (defvar mime-viewer/uuencode-encoding-name-list '("x-uue" "x-uuencode")) | |
154 | |
155 (defvar mime-viewer/ignored-field-list | |
156 '(".*Received" ".*Path" ".*Id" "References" | |
157 "Replied" "Errors-To" | |
158 "Lines" "Sender" ".*Host" "Xref" | |
159 "Content-Type" "Precedence" | |
160 "Status" "X-VM-.*") | |
161 "All fields that match this list will be hidden in MIME preview buffer. | |
162 Each elements are regexp of field-name. [tm-view.el]") | |
163 | |
164 (defvar mime-viewer/ignored-field-regexp | |
165 (concat "^" | |
166 (apply (function regexp-or) mime-viewer/ignored-field-list) | |
167 ":")) | |
168 | |
169 (defvar mime-viewer/visible-field-list | |
170 '("Dnas.*" "Message-Id") | |
171 "All fields that match this list will be displayed in MIME preview buffer. | |
172 Each elements are regexp of field-name. [tm-view.el]") | |
173 | |
174 (defvar mime-viewer/visible-field-regexp | |
175 (concat "^" | |
176 (apply (function regexp-or) mime-viewer/visible-field-list) | |
177 ":")) | |
178 | |
179 (defvar mime-viewer/redisplay nil) | |
180 | |
181 (defvar mime-viewer/announcement-for-message/partial | |
182 (if (and (>= emacs-major-version 19) window-system) | |
183 "\ | |
184 \[[ This is message/partial style split message. ]] | |
185 \[[ Please press `v' key in this buffer ]] | |
186 \[[ or click here by mouse button-2. ]]" | |
187 "\ | |
188 \[[ This is message/partial style split message. ]] | |
189 \[[ Please press `v' key in this buffer. ]]" | |
190 )) | |
191 | |
192 | |
193 ;;; @@ predicate functions | |
194 ;;; | |
195 | |
196 (defun mime-viewer/header-visible-p (rcnum cinfo &optional ctype) | |
197 (or (null rcnum) | |
198 (progn | |
199 (setq ctype | |
200 (mime::content-info/type | |
201 (mime-article/rcnum-to-cinfo (cdr rcnum) cinfo) | |
202 )) | |
203 (member ctype mime-viewer/childrens-header-showing-Content-Type-list) | |
204 ))) | |
205 | |
206 (defun mime-viewer/body-visible-p (rcnum cinfo &optional ctype) | |
207 (let (ccinfo) | |
208 (or ctype | |
209 (setq ctype | |
210 (mime::content-info/type | |
211 (setq ccinfo (mime-article/rcnum-to-cinfo rcnum cinfo)) | |
212 )) | |
213 ) | |
214 (and (member ctype mime-viewer/default-showing-Content-Type-list) | |
215 (if (string-equal ctype "application/octet-stream") | |
216 (progn | |
217 (or ccinfo | |
218 (setq ccinfo (mime-article/rcnum-to-cinfo rcnum cinfo)) | |
219 ) | |
220 (member (mime::content-info/encoding ccinfo) | |
221 '(nil "7bit" "8bit")) | |
222 ) | |
223 t)) | |
224 )) | |
225 | |
226 | |
227 ;;; @@ content button | |
228 ;;; | |
229 | |
230 (defun mime-preview/insert-content-button | |
231 (rcnum cinfo ctype params subj encoding) | |
232 (save-restriction | |
233 (narrow-to-region (point)(point)) | |
234 (let ((access-type (assoc "access-type" params)) | |
235 (charset (assoc "charset" params)) | |
236 (num (or (assoc-value "x-part-number" params) | |
237 (if (consp rcnum) | |
238 (mapconcat (function | |
239 (lambda (num) | |
240 (format "%s" (1+ num)) | |
241 )) | |
242 (reverse rcnum) ".") | |
243 "0")) | |
244 )) | |
245 (cond (access-type | |
246 (let ((server (assoc "server" params))) | |
247 (setq access-type (cdr access-type)) | |
248 (if server | |
249 (insert (format "[%s %s ([%s] %s)]\n" num subj | |
250 access-type (cdr server))) | |
251 (let ((site (assoc-value "site" params)) | |
252 (dir (assoc-value "directory" params)) | |
253 ) | |
254 (insert (format "[%s %s ([%s] %s:%s)]\n" num subj | |
255 access-type site dir)) | |
256 ))) | |
257 ) | |
258 (t | |
259 (insert (concat "[" num " " subj)) | |
260 (let ((rest | |
261 (if (setq charset (cdr charset)) | |
262 (if encoding | |
263 (format " <%s; %s (%s)>]\n" | |
264 ctype charset encoding) | |
265 (format " <%s; %s>]\n" ctype charset) | |
266 ) | |
267 (format " <%s>]\n" ctype) | |
268 ))) | |
269 (if (>= (+ (current-column)(length rest))(window-width)) | |
270 (setq rest (concat "\n\t" rest)) | |
271 ) | |
272 (insert rest) | |
273 )))) | |
274 (tm:add-button (point-min)(1- (point-max)) | |
275 (function mime-viewer/play-content)) | |
276 )) | |
277 | |
278 (defun mime-preview/default-content-button-function | |
279 (rcnum cinfo ctype params subj encoding) | |
280 (if (and (consp rcnum) | |
281 (not (member | |
282 ctype | |
283 mime-viewer/content-button-ignored-ctype-list))) | |
284 (mime-preview/insert-content-button | |
285 rcnum cinfo ctype params subj encoding) | |
286 )) | |
287 | |
288 (defvar mime-preview/content-button-function | |
289 (function mime-preview/default-content-button-function)) | |
290 | |
291 | |
292 ;;; @@ content header filter | |
293 ;;; | |
294 | |
295 (defun mime-preview/cut-header () | |
296 (goto-char (point-min)) | |
297 (while (and | |
298 (re-search-forward mime-viewer/ignored-field-regexp nil t) | |
299 (let* ((beg (match-beginning 0)) | |
300 (end (match-end 0)) | |
301 (name (buffer-substring beg end)) | |
302 ) | |
303 (if (not (string-match mime-viewer/visible-field-regexp name)) | |
304 (delete-region | |
305 beg | |
306 (save-excursion | |
307 (and | |
308 (re-search-forward "^\\([^ \t]\\|$\\)" nil t) | |
309 (match-beginning 0) | |
310 ))) | |
311 ) | |
312 t))) | |
313 ) | |
314 | |
315 (defun mime-viewer/default-content-header-filter () | |
316 (mime-preview/cut-header) | |
317 (mime/decode-message-header) | |
318 ) | |
319 | |
320 (defvar mime-viewer/content-header-filter-alist nil) | |
321 | |
322 | |
323 ;;; @@ content filter | |
324 ;;; | |
325 | |
326 (defvar mime-viewer/content-filter-alist | |
327 '(("text/enriched" . mime-preview/filter-for-text/enriched) | |
328 ("text/richtext" . mime-preview/filter-for-text/richtext) | |
329 (t . mime-preview/filter-for-text/plain) | |
330 )) | |
331 | |
332 | |
333 ;;; @@ content separator | |
334 ;;; | |
335 | |
336 (defun mime-preview/default-content-separator (rcnum cinfo ctype params subj) | |
337 (if (and (not (mime-viewer/header-visible-p rcnum cinfo ctype)) | |
338 (not (mime-viewer/body-visible-p rcnum cinfo ctype)) | |
339 ) | |
340 (progn | |
341 (goto-char (point-max)) | |
342 (insert "\n") | |
343 ))) | |
344 | |
345 | |
346 ;;; @@ buffer local variables | |
347 ;;; | |
348 | |
349 ;; for XEmacs | |
350 (defvar mime::article/preview-buffer nil) | |
351 (defvar mime::article/code-converter nil) | |
352 (defvar mime::preview/article-buffer nil) | |
353 | |
354 (make-variable-buffer-local 'mime::article/content-info) | |
355 (make-variable-buffer-local 'mime::article/preview-buffer) | |
356 (make-variable-buffer-local 'mime::article/code-converter) | |
357 | |
358 (make-variable-buffer-local 'mime::preview/mother-buffer) | |
359 (make-variable-buffer-local 'mime::preview/content-list) | |
360 (make-variable-buffer-local 'mime::preview/article-buffer) | |
361 (make-variable-buffer-local 'mime::preview/original-major-mode) | |
362 (make-variable-buffer-local 'mime::preview/original-window-configuration) | |
363 | |
364 | |
365 ;;; @@ quitting method | |
366 ;;; | |
367 | |
368 (defvar mime-viewer/quitting-method-alist | |
369 '((mime/show-message-mode | |
370 . mime-viewer/quitting-method-for-mime/show-message-mode))) | |
371 | |
372 (defvar mime-viewer/over-to-previous-method-alist nil) | |
373 (defvar mime-viewer/over-to-next-method-alist nil) | |
374 | |
375 (defvar mime-viewer/show-summary-method nil) | |
376 | |
377 | |
378 ;;; @@ following method | |
379 ;;; | |
380 | |
381 (defvar mime-viewer/following-method-alist nil) | |
382 | |
383 | |
384 ;;; @@ X-Face | |
385 ;;; | |
386 | |
387 ;; hack from Gnus 5.0.4. | |
388 | |
389 (defvar mime-viewer/x-face-to-pbm-command | |
390 "{ echo '/* Width=48, Height=48 */'; uncompface; } | icontopbm") | |
391 | |
392 (defvar mime-viewer/x-face-command | |
393 (concat mime-viewer/x-face-to-pbm-command | |
394 " | xv -quit -") | |
395 "String to be executed to display an X-Face field. | |
396 The command will be executed in a sub-shell asynchronously. | |
397 The compressed face will be piped to this command.") | |
398 | |
399 (defun mime-viewer/x-face-function () | |
400 "Function to display X-Face field. You can redefine to customize." | |
401 ;; 1995/10/12 (c.f. tm-eng:130) | |
402 ;; fixed by Eric Ding <ericding@San-Jose.ate.slb.com> | |
403 (save-restriction | |
404 (narrow-to-region (point-min) (re-search-forward "^$" nil t)) | |
405 ;; end | |
406 (goto-char (point-min)) | |
407 (if (re-search-forward "^X-Face:[ \t]*" nil t) | |
408 (let ((beg (match-end 0)) | |
409 (end (std11-field-end)) | |
410 ) | |
411 (call-process-region beg end "sh" nil 0 nil | |
412 "-c" mime-viewer/x-face-command) | |
413 )))) | |
414 | |
415 | |
416 ;;; @@ utility | |
417 ;;; | |
418 | |
419 (defun mime-preview/get-original-major-mode () | |
420 (if mime::preview/mother-buffer | |
421 (save-excursion | |
422 (set-buffer mime::preview/mother-buffer) | |
423 (mime-preview/get-original-major-mode) | |
424 ) | |
425 mime::preview/original-major-mode)) | |
426 | |
427 | |
428 ;;; @ data structures | |
429 ;;; | |
430 | |
431 ;;; @@ preview-content-info | |
432 ;;; | |
433 | |
434 (define-structure mime::preview-content-info | |
435 point-min point-max buffer content-info) | |
436 | |
437 | |
438 ;;; @ buffer setup | |
439 ;;; | |
440 | |
441 (defun mime-viewer/setup-buffer (&optional ctl encoding ibuf obuf) | |
442 (if ibuf | |
443 (progn | |
444 (get-buffer ibuf) | |
445 (set-buffer ibuf) | |
446 )) | |
447 (or mime-viewer/redisplay | |
448 (setq mime::article/content-info (mime/parse-message ctl encoding)) | |
449 ) | |
450 (let ((ret (mime-viewer/make-preview-buffer obuf))) | |
451 (setq mime::article/preview-buffer (car ret)) | |
452 ret)) | |
453 | |
454 (defun mime-viewer/make-preview-buffer (&optional obuf) | |
455 (let* ((cinfo mime::article/content-info) | |
456 (pcl (mime/flatten-content-info cinfo)) | |
457 (dest (make-list (length pcl) nil)) | |
458 (the-buf (current-buffer)) | |
459 (mode major-mode) | |
460 ) | |
461 (or obuf | |
462 (setq obuf (concat "*Preview-" (buffer-name the-buf) "*"))) | |
463 (set-buffer (get-buffer-create obuf)) | |
464 (setq buffer-read-only nil) | |
465 (widen) | |
466 (erase-buffer) | |
467 (setq mime::preview/article-buffer the-buf) | |
468 (setq mime::preview/original-major-mode mode) | |
469 (setq major-mode 'mime/viewer-mode) | |
470 (setq mode-name "MIME-View") | |
471 (let ((drest dest)) | |
472 (while pcl | |
473 (setcar drest | |
474 (mime-preview/display-content (car pcl) cinfo the-buf obuf)) | |
475 (setq pcl (cdr pcl) | |
476 drest (cdr drest)) | |
477 )) | |
478 (set-buffer-modified-p nil) | |
479 (setq buffer-read-only t) | |
480 (set-buffer the-buf) | |
481 (list obuf dest) | |
482 )) | |
483 | |
484 (defun mime-preview/display-content (content cinfo ibuf obuf) | |
485 (let* ((beg (mime::content-info/point-min content)) | |
486 (end (mime::content-info/point-max content)) | |
487 (ctype (mime::content-info/type content)) | |
488 (params (mime::content-info/parameters content)) | |
489 (encoding (mime::content-info/encoding content)) | |
490 (rcnum (mime::content-info/rcnum content)) | |
491 he e nb ne subj) | |
492 (set-buffer ibuf) | |
493 (goto-char beg) | |
494 (setq he (if (re-search-forward "^$" nil t) | |
495 (1+ (match-end 0)) | |
496 end)) | |
497 (if (> he end) | |
498 (setq he end) | |
499 ) | |
500 (save-restriction | |
501 (narrow-to-region beg end) | |
502 (setq subj | |
503 (mime-eword/decode-string | |
504 (mime-article/get-subject params encoding))) | |
505 ) | |
506 (set-buffer obuf) | |
507 (setq nb (point)) | |
508 (narrow-to-region nb nb) | |
509 (funcall mime-preview/content-button-function | |
510 rcnum cinfo ctype params subj encoding) | |
511 (if (mime-viewer/header-visible-p rcnum cinfo ctype) | |
512 (mime-preview/display-header beg he) | |
513 ) | |
514 (if (and (null rcnum) | |
515 (member | |
516 ctype mime-viewer/content-button-visible-ctype-list)) | |
517 (save-excursion | |
518 (goto-char (point-max)) | |
519 (mime-preview/insert-content-button | |
520 rcnum cinfo ctype params subj encoding) | |
521 )) | |
522 (cond ((mime-viewer/body-visible-p rcnum cinfo ctype) | |
523 (mime-preview/display-body he end | |
524 rcnum cinfo ctype params subj encoding) | |
525 ) | |
526 ((equal ctype "message/partial") | |
527 (mime-preview/display-message/partial) | |
528 ) | |
529 ((and (null rcnum) | |
530 (null (mime::content-info/children cinfo)) | |
531 ) | |
532 (goto-char (point-max)) | |
533 (mime-preview/insert-content-button | |
534 rcnum cinfo ctype params subj encoding) | |
535 )) | |
536 (mime-preview/default-content-separator rcnum cinfo ctype params subj) | |
537 (prog1 | |
538 (progn | |
539 (setq ne (point-max)) | |
540 (widen) | |
541 (mime::preview-content-info/create nb (1- ne) ibuf content) | |
542 ) | |
543 (goto-char ne) | |
544 ))) | |
545 | |
546 (defun mime-preview/display-header (beg end) | |
547 (save-restriction | |
548 (narrow-to-region (point)(point)) | |
549 (insert-buffer-substring mime::preview/article-buffer beg end) | |
550 (let ((f (cdr (assq mime::preview/original-major-mode | |
551 mime-viewer/content-header-filter-alist)))) | |
552 (if (functionp f) | |
553 (funcall f) | |
554 (mime-viewer/default-content-header-filter) | |
555 )) | |
556 (run-hooks 'mime-viewer/content-header-filter-hook) | |
557 )) | |
558 | |
559 (defun mime-preview/display-body (beg end | |
560 rcnum cinfo ctype params subj encoding) | |
561 (save-restriction | |
562 (narrow-to-region (point-max)(point-max)) | |
563 (insert-buffer-substring mime::preview/article-buffer beg end) | |
564 (let ((f (cdr (or (assoc ctype mime-viewer/content-filter-alist) | |
565 (assq t mime-viewer/content-filter-alist))))) | |
566 (and (functionp f) | |
567 (funcall f ctype params encoding) | |
568 ) | |
569 ))) | |
570 | |
571 (defun mime-preview/display-message/partial () | |
572 (save-restriction | |
573 (goto-char (point-max)) | |
574 (if (not (search-backward "\n\n" nil t)) | |
575 (insert "\n") | |
576 ) | |
577 (let ((be (point-max))) | |
578 (narrow-to-region be be) | |
579 (insert mime-viewer/announcement-for-message/partial) | |
580 (tm:add-button (point-min)(point-max) | |
581 (function mime-viewer/play-content)) | |
582 ))) | |
583 | |
584 (defun mime-article/get-uu-filename (param &optional encoding) | |
585 (if (member (or encoding | |
586 (cdr (assq 'encoding param)) | |
587 ) | |
588 mime-viewer/uuencode-encoding-name-list) | |
589 (save-excursion | |
590 (or (if (re-search-forward "^begin [0-9]+ " nil t) | |
591 (if (looking-at ".+$") | |
592 (buffer-substring (match-beginning 0)(match-end 0)) | |
593 )) | |
594 "")) | |
595 )) | |
596 | |
597 (defun mime-article/get-subject (param &optional encoding) | |
598 (or (std11-find-field-body '("Content-Description" "Subject")) | |
599 (let (ret) | |
600 (if (or (and (setq ret (mime/Content-Disposition)) | |
601 (setq ret (assoc "filename" (cdr ret))) | |
602 ) | |
603 (setq ret (assoc "name" param)) | |
604 (setq ret (assoc "x-name" param)) | |
605 ) | |
606 (std11-strip-quoted-string (cdr ret)) | |
607 )) | |
608 (mime-article/get-uu-filename param encoding) | |
609 "")) | |
610 | |
611 | |
612 ;;; @ content information | |
613 ;;; | |
614 | |
615 (defun mime-article/point-content-number (p &optional cinfo) | |
616 (or cinfo | |
617 (setq cinfo mime::article/content-info) | |
618 ) | |
619 (let ((b (mime::content-info/point-min cinfo)) | |
620 (e (mime::content-info/point-max cinfo)) | |
621 (c (mime::content-info/children cinfo)) | |
622 ) | |
623 (if (and (<= b p)(<= p e)) | |
624 (or (let (co ret (sn 0)) | |
625 (catch 'tag | |
626 (while c | |
627 (setq co (car c)) | |
628 (setq ret (mime-article/point-content-number p co)) | |
629 (cond ((eq ret t) (throw 'tag (list sn))) | |
630 (ret (throw 'tag (cons sn ret))) | |
631 ) | |
632 (setq c (cdr c)) | |
633 (setq sn (1+ sn)) | |
634 ))) | |
635 t)))) | |
636 | |
637 (defun mime-article/rcnum-to-cinfo (rcnum &optional cinfo) | |
638 (or cinfo | |
639 (setq cinfo mime::article/content-info) | |
640 ) | |
641 (find-if (function | |
642 (lambda (ci) | |
643 (equal (mime::content-info/rcnum ci) rcnum) | |
644 )) | |
645 (mime/flatten-content-info cinfo) | |
646 )) | |
647 | |
648 (defun mime-article/cnum-to-cinfo (cn &optional cinfo) | |
649 (or cinfo | |
650 (setq cinfo mime::article/content-info) | |
651 ) | |
652 (if (eq cn t) | |
653 cinfo | |
654 (let ((sn (car cn))) | |
655 (if (null sn) | |
656 cinfo | |
657 (let ((rc (nth sn (mime::content-info/children cinfo)))) | |
658 (if rc | |
659 (mime-article/cnum-to-cinfo (cdr cn) rc) | |
660 )) | |
661 )))) | |
662 | |
663 (defun mime/flatten-content-info (&optional cinfo) | |
664 (or cinfo | |
665 (setq cinfo mime::article/content-info) | |
666 ) | |
667 (let ((dest (list cinfo)) | |
668 (rcl (mime::content-info/children cinfo)) | |
669 ) | |
670 (while rcl | |
671 (setq dest (nconc dest (mime/flatten-content-info (car rcl)))) | |
672 (setq rcl (cdr rcl)) | |
673 ) | |
674 dest)) | |
675 | |
676 (defun mime-preview/point-pcinfo (p &optional pcl) | |
677 (or pcl | |
678 (setq pcl mime::preview/content-list) | |
679 ) | |
680 (catch 'tag | |
681 (let ((r pcl) cell) | |
682 (while r | |
683 (setq cell (car r)) | |
684 (if (and (<= (mime::preview-content-info/point-min cell) p) | |
685 (<= p (mime::preview-content-info/point-max cell)) | |
686 ) | |
687 (throw 'tag cell) | |
688 ) | |
689 (setq r (cdr r)) | |
690 )) | |
691 (car (last pcl)) | |
692 )) | |
693 | |
694 | |
695 ;;; @ MIME viewer mode | |
696 ;;; | |
697 | |
698 (defconst mime-viewer/menu-title "MIME-View") | |
699 (defconst mime-viewer/menu-list | |
700 '((up "Move to upper content" mime-viewer/up-content) | |
701 (previous "Move to previous content" mime-viewer/previous-content) | |
702 (next "Move to next content" mime-viewer/next-content) | |
703 (scroll-down "Scroll to previous content" mime-viewer/scroll-down-content) | |
704 (scroll-up "Scroll to next content" mime-viewer/scroll-up-content) | |
705 (play "Play Content" mime-viewer/play-content) | |
706 (extract "Extract Content" mime-viewer/extract-content) | |
707 (print "Print" mime-viewer/print-content) | |
708 (x-face "Show X Face" mime-viewer/display-x-face) | |
709 ) | |
710 "Menu for MIME Viewer") | |
711 | |
712 (if running-xemacs | |
713 (progn | |
714 (defvar mime-viewer/xemacs-popup-menu | |
715 (cons mime-viewer/menu-title | |
716 (mapcar (function | |
717 (lambda (item) | |
718 (vector (nth 1 item)(nth 2 item) t) | |
719 )) | |
720 mime-viewer/menu-list))) | |
721 (defun mime-viewer/xemacs-popup-menu (event) | |
722 "Popup the menu in the MIME Viewer buffer" | |
723 (interactive "e") | |
724 (select-window (event-window event)) | |
725 (set-buffer (event-buffer event)) | |
726 (popup-menu 'mime-viewer/xemacs-popup-menu)) | |
727 )) | |
728 | |
729 (defun mime-viewer/define-keymap (&optional mother) | |
730 (let ((mime/viewer-mode-map (if mother | |
731 (copy-keymap mother) | |
732 (make-keymap)))) | |
733 (suppress-keymap mime/viewer-mode-map) | |
734 (define-key mime/viewer-mode-map | |
735 "u" (function mime-viewer/up-content)) | |
736 (define-key mime/viewer-mode-map | |
737 "p" (function mime-viewer/previous-content)) | |
738 (define-key mime/viewer-mode-map | |
739 "n" (function mime-viewer/next-content)) | |
740 (define-key mime/viewer-mode-map | |
741 " " (function mime-viewer/scroll-up-content)) | |
742 (define-key mime/viewer-mode-map | |
743 "\M- " (function mime-viewer/scroll-down-content)) | |
744 (define-key mime/viewer-mode-map | |
745 "\177" (function mime-viewer/scroll-down-content)) | |
746 (define-key mime/viewer-mode-map | |
747 "\C-m" (function mime-viewer/next-line-content)) | |
748 (define-key mime/viewer-mode-map | |
749 "\C-\M-m" (function mime-viewer/previous-line-content)) | |
750 (define-key mime/viewer-mode-map | |
751 "v" (function mime-viewer/play-content)) | |
752 (define-key mime/viewer-mode-map | |
753 "e" (function mime-viewer/extract-content)) | |
754 (define-key mime/viewer-mode-map | |
755 "\C-c\C-p" (function mime-viewer/print-content)) | |
756 (define-key mime/viewer-mode-map | |
757 "x" (function mime-viewer/display-x-face)) | |
758 (define-key mime/viewer-mode-map | |
759 "a" (function mime-viewer/follow-content)) | |
760 (define-key mime/viewer-mode-map | |
761 "q" (function mime-viewer/quit)) | |
762 (define-key mime/viewer-mode-map | |
763 "h" (function mime-viewer/show-summary)) | |
764 (define-key mime/viewer-mode-map | |
765 "\C-c\C-x" (function mime-viewer/kill-buffer)) | |
766 (define-key mime/viewer-mode-map | |
767 "<" (function beginning-of-buffer)) | |
768 (define-key mime/viewer-mode-map | |
769 ">" (function end-of-buffer)) | |
770 (define-key mime/viewer-mode-map | |
771 "?" (function describe-mode)) | |
772 (if mouse-button-2 | |
773 (define-key mime/viewer-mode-map | |
774 mouse-button-2 (function tm:button-dispatcher)) | |
775 ) | |
776 (cond (running-xemacs | |
777 (define-key mime/viewer-mode-map | |
778 mouse-button-3 (function mime-viewer/xemacs-popup-menu)) | |
779 ) | |
780 ((>= emacs-major-version 19) | |
781 (define-key mime/viewer-mode-map [menu-bar mime-view] | |
782 (cons mime-viewer/menu-title | |
783 (make-sparse-keymap mime-viewer/menu-title))) | |
784 (mapcar (function | |
785 (lambda (item) | |
786 (define-key mime/viewer-mode-map | |
787 (vector 'menu-bar 'mime-view (car item)) | |
788 (cons (nth 1 item)(nth 2 item)) | |
789 ) | |
790 )) | |
791 (reverse mime-viewer/menu-list) | |
792 ) | |
793 )) | |
794 (use-local-map mime/viewer-mode-map) | |
795 (run-hooks 'mime-viewer/define-keymap-hook) | |
796 )) | |
797 | |
798 (defun mime/viewer-mode (&optional mother ctl encoding ibuf obuf | |
799 mother-keymap) | |
800 "Major mode for viewing MIME message. | |
801 | |
802 Here is a list of the standard keys for mime/viewer-mode. | |
803 | |
804 key feature | |
805 --- ------- | |
806 | |
807 u Move to upper content | |
808 p Move to previous content | |
809 n Move to next content | |
810 SPC Scroll up or move to next content | |
811 M-SPC Scroll down or move to previous content | |
812 DEL Scroll down or move to previous content | |
813 RET Move to next line | |
814 M-RET Move to previous line | |
815 v Decode current content as `play mode' | |
816 e Decode current content as `extract mode' | |
817 C-c C-p Decode current content as `print mode' | |
818 a Followup to current content. | |
819 x Display X-Face | |
820 q Quit | |
821 button-2 Move to point under the mouse cursor | |
822 and decode current content as `play mode' | |
823 " | |
824 (interactive) | |
825 (let ((buf (get-buffer mime/output-buffer-name))) | |
826 (if buf | |
827 (save-excursion | |
828 (set-buffer buf) | |
829 (erase-buffer) | |
830 ))) | |
831 (let ((ret (mime-viewer/setup-buffer ctl encoding ibuf obuf)) | |
832 (win-conf (current-window-configuration)) | |
833 ) | |
834 (prog1 | |
835 (switch-to-buffer (car ret)) | |
836 (setq mime::preview/original-window-configuration win-conf) | |
837 (if mother | |
838 (progn | |
839 (setq mime::preview/mother-buffer mother) | |
840 )) | |
841 (mime-viewer/define-keymap mother-keymap) | |
842 (setq mime::preview/content-list (nth 1 ret)) | |
843 (goto-char | |
844 (let ((ce (mime::preview-content-info/point-max | |
845 (car mime::preview/content-list) | |
846 )) | |
847 e) | |
848 (goto-char (point-min)) | |
849 (search-forward "\n\n" nil t) | |
850 (setq e (match-end 0)) | |
851 (if (<= e ce) | |
852 e | |
853 ce))) | |
854 (run-hooks 'mime/viewer-mode-hook) | |
855 ))) | |
856 | |
857 (defun mime-preview/point-content-number (point) | |
858 (save-window-excursion | |
859 (let ((pc (mime-preview/point-pcinfo (point))) | |
860 cinfo) | |
861 (switch-to-buffer (mime::preview-content-info/buffer pc)) | |
862 (setq cinfo (mime::preview-content-info/content-info pc)) | |
863 (mime-article/point-content-number (mime::content-info/point-min cinfo)) | |
864 ))) | |
865 | |
866 (defun mime-preview/cinfo-to-pcinfo (cinfo) | |
867 (let ((rpcl mime::preview/content-list) cell) | |
868 (catch 'tag | |
869 (while rpcl | |
870 (setq cell (car rpcl)) | |
871 (if (eq cinfo (mime::preview-content-info/content-info cell)) | |
872 (throw 'tag cell) | |
873 ) | |
874 (setq rpcl (cdr rpcl)) | |
875 )))) | |
876 | |
877 (autoload 'mime-preview/decode-content "tm-play") | |
878 | |
879 (defvar mime-viewer/decoding-mode "play" "MIME body decoding mode") | |
880 | |
881 (defun mime-viewer/play-content () | |
882 (interactive) | |
883 (let ((mime-viewer/decoding-mode "play")) | |
884 (mime-preview/decode-content) | |
885 )) | |
886 | |
887 (defun mime-viewer/extract-content () | |
888 (interactive) | |
889 (let ((mime-viewer/decoding-mode "extract")) | |
890 (mime-preview/decode-content) | |
891 )) | |
892 | |
893 (defun mime-viewer/print-content () | |
894 (interactive) | |
895 (let ((mime-viewer/decoding-mode "print")) | |
896 (mime-preview/decode-content) | |
897 )) | |
898 | |
899 (defun mime-viewer/follow-content () | |
900 (interactive) | |
901 (let ((root-cinfo | |
902 (mime::preview-content-info/content-info | |
903 (car mime::preview/content-list))) | |
904 pc p-beg p-end cinfo rcnum) | |
905 (let ((rest mime::preview/content-list) | |
906 b e cell len rc) | |
907 (if (catch 'tag | |
908 (while (setq cell (car rest)) | |
909 (setq b (mime::preview-content-info/point-min cell) | |
910 e (mime::preview-content-info/point-max cell)) | |
911 (setq rest (cdr rest)) | |
912 (if (and (<= b (point))(<= (point) e)) | |
913 (throw 'tag cell) | |
914 ) | |
915 )) | |
916 (progn | |
917 (setq pc cell | |
918 cinfo (mime::preview-content-info/content-info pc) | |
919 rcnum (mime::content-info/rcnum cinfo)) | |
920 (setq len (length rcnum)) | |
921 (setq p-beg (mime::preview-content-info/point-min pc) | |
922 p-end (mime::preview-content-info/point-max pc)) | |
923 (while (and (setq cell (car rest)) | |
924 (progn | |
925 (setq rc | |
926 (mime::content-info/rcnum | |
927 (mime::preview-content-info/content-info | |
928 cell))) | |
929 (equal rcnum | |
930 (nthcdr (- (length rc) len) rc)) | |
931 )) | |
932 (setq p-end (mime::preview-content-info/point-max cell)) | |
933 (setq rest (cdr rest)) | |
934 )))) | |
935 (if pc | |
936 (let* ((mode (mime-preview/get-original-major-mode)) | |
937 (new-name (format "%s-%s" (buffer-name) (reverse rcnum))) | |
938 new-buf | |
939 (the-buf (current-buffer)) | |
940 (a-buf mime::preview/article-buffer) | |
941 (hb (mime::content-info/point-min cinfo)) | |
942 (he (mime::content-info/point-max cinfo)) | |
943 fields from to cc reply-to subj mid f) | |
944 (save-excursion | |
945 (set-buffer (setq new-buf (get-buffer-create new-name))) | |
946 (erase-buffer) | |
947 (insert-buffer-substring the-buf p-beg p-end) | |
948 (goto-char (point-min)) | |
949 (if (mime-viewer/header-visible-p rcnum root-cinfo) | |
950 (delete-region (goto-char (point-min)) | |
951 (if (re-search-forward "^$" nil t) | |
952 (match-end 0) | |
953 (point-min))) | |
954 ) | |
955 (goto-char (point-min)) | |
956 (insert "\n") | |
957 (goto-char (point-min)) | |
958 (let ((rcnum (mime::content-info/rcnum cinfo)) ci str) | |
959 (while (progn | |
960 (setq str | |
961 (save-excursion | |
962 (set-buffer a-buf) | |
963 (setq ci (mime-article/rcnum-to-cinfo rcnum)) | |
964 (save-restriction | |
965 (narrow-to-region | |
966 (mime::content-info/point-min ci) | |
967 (mime::content-info/point-max ci) | |
968 ) | |
969 (std11-header-string-except | |
970 (concat "^" | |
971 (apply (function regexp-or) fields) | |
972 ":") "")))) | |
973 (if (string-equal (mime::content-info/type ci) | |
974 "message/rfc822") | |
975 nil | |
976 (if str | |
977 (insert str) | |
978 ) | |
979 rcnum)) | |
980 (setq fields (std11-collect-field-names) | |
981 rcnum (cdr rcnum)) | |
982 ) | |
983 ) | |
984 (mime/decode-message-header) | |
985 ) | |
986 (funcall (cdr (assq mode mime-viewer/following-method-alist)) | |
987 new-buf) | |
988 )))) | |
989 | |
990 (defun mime-viewer/display-x-face () | |
991 (interactive) | |
992 (save-window-excursion | |
993 (set-buffer mime::preview/article-buffer) | |
994 (mime-viewer/x-face-function) | |
995 )) | |
996 | |
997 (defun mime-viewer/up-content () | |
998 (interactive) | |
999 (let* ((pc (mime-preview/point-pcinfo (point))) | |
1000 (cinfo (mime::preview-content-info/content-info pc)) | |
1001 (rcnum (mime::content-info/rcnum cinfo)) | |
1002 ) | |
1003 (if rcnum | |
1004 (let ((r (save-excursion | |
1005 (set-buffer (mime::preview-content-info/buffer pc)) | |
1006 (mime-article/rcnum-to-cinfo (cdr rcnum)) | |
1007 )) | |
1008 (rpcl mime::preview/content-list) | |
1009 cell) | |
1010 (while (and | |
1011 (setq cell (car rpcl)) | |
1012 (not (eq r (mime::preview-content-info/content-info cell))) | |
1013 ) | |
1014 (setq rpcl (cdr rpcl)) | |
1015 ) | |
1016 (goto-char (mime::preview-content-info/point-min cell)) | |
1017 ) | |
1018 (mime-viewer/quit) | |
1019 ))) | |
1020 | |
1021 (defun mime-viewer/previous-content () | |
1022 (interactive) | |
1023 (let* ((pcl mime::preview/content-list) | |
1024 (p (point)) | |
1025 (i (- (length pcl) 1)) | |
1026 beg) | |
1027 (catch 'tag | |
1028 (while (>= i 0) | |
1029 (setq beg (mime::preview-content-info/point-min (nth i pcl))) | |
1030 (if (> p beg) | |
1031 (throw 'tag (goto-char beg)) | |
1032 ) | |
1033 (setq i (- i 1)) | |
1034 ) | |
1035 (let ((f (assq mime::preview/original-major-mode | |
1036 mime-viewer/over-to-previous-method-alist))) | |
1037 (if f | |
1038 (funcall (cdr f)) | |
1039 )) | |
1040 ) | |
1041 )) | |
1042 | |
1043 (defun mime-viewer/next-content () | |
1044 (interactive) | |
1045 (let ((pcl mime::preview/content-list) | |
1046 (p (point)) | |
1047 beg) | |
1048 (catch 'tag | |
1049 (while pcl | |
1050 (setq beg (mime::preview-content-info/point-min (car pcl))) | |
1051 (if (< p beg) | |
1052 (throw 'tag (goto-char beg)) | |
1053 ) | |
1054 (setq pcl (cdr pcl)) | |
1055 ) | |
1056 (let ((f (assq mime::preview/original-major-mode | |
1057 mime-viewer/over-to-next-method-alist))) | |
1058 (if f | |
1059 (funcall (cdr f)) | |
1060 )) | |
1061 ) | |
1062 )) | |
1063 | |
1064 (defun mime-viewer/scroll-up-content (&optional h) | |
1065 (interactive) | |
1066 (or h | |
1067 (setq h (- (window-height) 1)) | |
1068 ) | |
1069 (if (= (point) (point-max)) | |
1070 (let ((f (assq mime::preview/original-major-mode | |
1071 mime-viewer/over-to-next-method-alist))) | |
1072 (if f | |
1073 (funcall (cdr f)) | |
1074 )) | |
1075 (let ((pcl mime::preview/content-list) | |
1076 (p (point)) | |
1077 np beg) | |
1078 (setq np | |
1079 (or (catch 'tag | |
1080 (while pcl | |
1081 (setq beg (mime::preview-content-info/point-min (car pcl))) | |
1082 (if (< p beg) | |
1083 (throw 'tag beg) | |
1084 ) | |
1085 (setq pcl (cdr pcl)) | |
1086 )) | |
1087 (point-max))) | |
1088 (forward-line h) | |
1089 (if (> (point) np) | |
1090 (goto-char np) | |
1091 ) | |
1092 ;;(show-subtree) | |
1093 )) | |
1094 ) | |
1095 | |
1096 (defun mime-viewer/scroll-down-content (&optional h) | |
1097 (interactive) | |
1098 (or h | |
1099 (setq h (- (window-height) 1)) | |
1100 ) | |
1101 (if (= (point) (point-min)) | |
1102 (let ((f (assq mime::preview/original-major-mode | |
1103 mime-viewer/over-to-previous-method-alist))) | |
1104 (if f | |
1105 (funcall (cdr f)) | |
1106 )) | |
1107 (let ((pcl mime::preview/content-list) | |
1108 (p (point)) | |
1109 pp beg) | |
1110 (setq pp | |
1111 (or (let ((i (- (length pcl) 1))) | |
1112 (catch 'tag | |
1113 (while (> i 0) | |
1114 (setq beg (mime::preview-content-info/point-min | |
1115 (nth i pcl))) | |
1116 (if (> p beg) | |
1117 (throw 'tag beg) | |
1118 ) | |
1119 (setq i (- i 1)) | |
1120 ))) | |
1121 (point-min))) | |
1122 (forward-line (- h)) | |
1123 (if (< (point) pp) | |
1124 (goto-char pp) | |
1125 ))) | |
1126 ) | |
1127 | |
1128 (defun mime-viewer/next-line-content () | |
1129 (interactive) | |
1130 (mime-viewer/scroll-up-content 1) | |
1131 ) | |
1132 | |
1133 (defun mime-viewer/previous-line-content () | |
1134 (interactive) | |
1135 (mime-viewer/scroll-down-content 1) | |
1136 ) | |
1137 | |
1138 (defun mime-viewer/quit () | |
1139 (interactive) | |
1140 (let ((r (save-excursion | |
1141 (set-buffer (mime::preview-content-info/buffer | |
1142 (mime-preview/point-pcinfo (point)))) | |
1143 (assq major-mode mime-viewer/quitting-method-alist) | |
1144 ))) | |
1145 (if r | |
1146 (funcall (cdr r)) | |
1147 ))) | |
1148 | |
1149 (defun mime-viewer/show-summary () | |
1150 (interactive) | |
1151 (let ((r (save-excursion | |
1152 (set-buffer | |
1153 (mime::preview-content-info/buffer | |
1154 (mime-preview/point-pcinfo (point))) | |
1155 ) | |
1156 (assq major-mode mime-viewer/show-summary-method) | |
1157 ))) | |
1158 (if r | |
1159 (funcall (cdr r)) | |
1160 ))) | |
1161 | |
1162 (defun mime-viewer/kill-buffer () | |
1163 (interactive) | |
1164 (kill-buffer (current-buffer)) | |
1165 ) | |
1166 | |
1167 | |
1168 ;;; @ end | |
1169 ;;; | |
1170 | |
1171 (provide 'tm-view) | |
1172 | |
1173 (run-hooks 'tm-view-load-hook) | |
1174 | |
1175 ;;; tm-view.el ends here |