tm 7.80.
[elisp/tm.git] / tm-play.el
1 ;;; tm-play.el --- decoder for tm-view.el
2
3 ;; Copyright (C) 1994,1995,1996 Free Software Foundation, Inc.
4
5 ;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
6 ;; Created: 1995/9/26 (separated from tm-view.el)
7 ;; Version: $Id: tm-play.el,v 7.26 1996/08/30 16:42:15 morioka Exp $
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 this program; see the file COPYING.  If not, write to
24 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 ;; Boston, MA 02111-1307, USA.
26
27 ;;; Code:
28
29 (require 'tm-view)
30
31 (defvar mime-viewer/external-progs "/usr/local/share/tm"
32   "*Directory containing tm external methods.")
33
34 (add-to-list 'exec-path mime-viewer/external-progs)
35
36              
37 ;;; @ content decoder
38 ;;;
39
40 (defvar mime-preview/after-decoded-position nil)
41
42 (defun mime-preview/decode-content ()
43   (interactive)
44   (let ((pc (mime-preview/point-pcinfo (point))))
45     (if pc
46         (let ((the-buf (current-buffer)))
47           (setq mime-preview/after-decoded-position (point))
48           (set-buffer (mime::preview-content-info/buffer pc))
49           (mime-article/decode-content
50            (mime::preview-content-info/content-info pc))
51           (if (eq (current-buffer)
52                   (mime::preview-content-info/buffer pc))
53               (progn
54                 (set-buffer the-buf)
55                 (goto-char mime-preview/after-decoded-position)
56                 ))
57           ))))
58
59 (defun mime-article/decode-content (cinfo)
60   (let ((beg (mime::content-info/point-min cinfo))
61         (end (mime::content-info/point-max cinfo))
62         (ctype (or (mime::content-info/type cinfo) "text/plain"))
63         (params (mime::content-info/parameters cinfo))
64         (encoding (mime::content-info/encoding cinfo))
65         )
66     ;; Check for VM
67     (if (< beg (point-min))
68         (setq beg (point-min))
69       )
70     (if (< (point-max) end)
71         (setq end (point-max))
72       )
73     (let (method cal ret)
74       (setq cal (list* (cons 'type ctype)
75                        (cons 'encoding encoding)
76                        (cons 'major-mode major-mode)
77                        params))
78       (if mime-viewer/decoding-mode
79           (setq cal (cons
80                      (cons 'mode mime-viewer/decoding-mode)
81                      cal))
82         )
83       (setq ret (mime/get-content-decoding-alist cal))
84       (setq method (cdr (assq 'method ret)))
85       (cond ((and (symbolp method)
86                   (fboundp method))
87              (funcall method beg end ret)
88              )
89             ((and (listp method)(stringp (car method)))
90              (mime-article/start-external-method-region beg end ret)
91              )
92             (t
93              (mime-article/show-output-buffer
94               "No method are specified for %s\n" ctype)
95              ))
96       )
97     ))
98
99 (defun mime/get-content-decoding-alist (al)
100   (get-unified-alist mime/content-decoding-condition al)
101   )
102
103
104 ;;; @ external decoder
105 ;;;
106
107 (defun mime-article/start-external-method-region (beg end cal)
108   (save-excursion
109     (save-restriction
110       (narrow-to-region beg end)
111       (goto-char beg)
112       (let ((method (cdr (assoc 'method cal)))
113             (name (mime-article/get-filename cal))
114             )
115         (if method
116             (let ((file (make-temp-name
117                          (expand-file-name "TM" mime/tmp-dir)))
118                   b args)
119               (if (nth 1 method)
120                   (setq b beg)
121                 (setq b
122                       (if (re-search-forward "^$" nil t)
123                           (1+ (match-end 0))
124                         (point-min)
125                         ))
126                 )
127               (goto-char b)
128               (write-region b end file)
129               (message "External method is starting...")
130               (setq cal (put-alist
131                          'name (replace-as-filename name) cal))
132               (setq cal (put-alist 'file file cal))
133               (setq args (nconc
134                           (list (car method)
135                                 mime/output-buffer-name (car method)
136                                 )
137                           (mime-article/make-method-args cal
138                                                          (cdr (cdr method)))
139                           ))
140               (let ((process-environment
141                      (let* ((rest process-environment)
142                             (dest (cons nil nil))
143                             (prest dest)
144                             (path nil)
145                             cell)
146                        (while (and (setq cell (car rest))
147                                    (not
148                                     (if (string-match "^PATH=" cell)
149                                         (setq path
150                                               (format
151                                                "PATH=%s:%s"
152                                                mime-viewer/external-progs
153                                                (substring cell (match-end 0))
154                                                )))))
155                          (setcar prest cell)
156                          (setcdr prest (cons nil nil))
157                          (setq rest (cdr rest)
158                                prest (cdr prest))
159                          )
160                        (setcar
161                         prest
162                         (or path
163                             (format "PATH=%s" mime-viewer/external-progs)))
164                        (setcdr prest (cdr rest))
165                        dest)))
166                 (apply (function start-process) args)
167                 )
168               (mime-article/show-output-buffer)
169               ))
170         ))))
171
172 (defun mime-article/make-method-args (cal format)
173   (mapcar (function
174            (lambda (arg)
175              (if (stringp arg)
176                  arg
177                (let* ((item (eval arg))
178                       (ret (cdr (assoc item cal)))
179                       )
180                  (if ret
181                      ret
182                    (if (eq item 'encoding)
183                        "7bit"
184                      ""))
185                  ))
186              ))
187           format))
188
189 (defun mime-article/show-output-buffer (&rest forms)
190   (get-buffer-create mime/output-buffer-name)
191   (let ((the-win (selected-window))
192         (win (get-buffer-window mime/output-buffer-name))
193         )
194     (or win
195         (if (and mime/output-buffer-window-is-shared-with-bbdb
196                  (boundp 'bbdb-buffer-name)
197                  (setq win (get-buffer-window bbdb-buffer-name))
198                  )
199             (set-window-buffer win mime/output-buffer-name)
200           (select-window (get-buffer-window mime::article/preview-buffer))
201           (setq win (split-window-vertically (/ (* (window-height) 3) 4)))
202           (set-window-buffer win mime/output-buffer-name)
203           ))
204     (select-window win)
205     (goto-char (point-max))
206     (if forms
207         (insert (apply (function format) forms))
208       )
209     (select-window the-win)
210     ))
211
212
213 ;;; @ file name
214 ;;;
215
216 (defvar mime-viewer/file-name-char-regexp "[A-Za-z0-9+_-]")
217
218 (defvar mime-viewer/file-name-regexp-1
219   (concat mime-viewer/file-name-char-regexp "+\\."
220           mime-viewer/file-name-char-regexp "+"))
221
222 (defvar mime-viewer/file-name-regexp-2
223   (concat (regexp-* mime-viewer/file-name-char-regexp)
224           "\\(\\." mime-viewer/file-name-char-regexp "+\\)*"))
225
226 (defun mime-article/get-original-filename (param &optional encoding)
227   (or (mime-article/get-uu-filename param encoding)
228       (let (ret)
229         (or (if (or (and (setq ret (mime/Content-Disposition))
230                          (setq ret (assoc "filename" (cdr ret)))
231                          )
232                     (setq ret (assoc "name" param))
233                     (setq ret (assoc "x-name" param))
234                     )
235                 (rfc822/strip-quoted-string (cdr ret))
236               )
237             (if (setq ret
238                       (std11-find-field-body '("Content-Description"
239                                                "Subject")))
240                 (if (or (string-match mime-viewer/file-name-regexp-1 ret)
241                         (string-match mime-viewer/file-name-regexp-2 ret))
242                     (substring ret (match-beginning 0)(match-end 0))
243                   ))
244             ))
245       ))
246
247 (defun mime-article/get-filename (param)
248   (replace-as-filename (mime-article/get-original-filename param))
249   )
250
251
252 ;;; @ mail/news message
253 ;;;
254
255 (defun mime-viewer/quitting-method-for-mime/show-message-mode ()
256   (let ((mother mime::preview/mother-buffer)
257         (win-conf mime::preview/original-window-configuration)
258         )
259     (kill-buffer
260      (mime::preview-content-info/buffer (car mime::preview/content-list)))
261     (mime-viewer/kill-buffer)
262     (set-window-configuration win-conf)
263     (pop-to-buffer mother)
264     ;;(goto-char (point-min))
265     ;;(mime-viewer/up-content)
266     ))
267
268 (defun mime-article/view-message/rfc822 (beg end cal)
269   (let* ((cnum (mime-article/point-content-number beg))
270          (cur-buf (current-buffer))
271          (new-name (format "%s-%s" (buffer-name) cnum))
272          (mother mime::article/preview-buffer)
273          (code-converter
274           (or (cdr (assq major-mode mime-viewer/code-converter-alist))
275               'mime-viewer/default-code-convert-region))
276          str)
277     (setq str (buffer-substring beg end))
278     (switch-to-buffer new-name)
279     (erase-buffer)
280     (insert str)
281     (goto-char (point-min))
282     (if (re-search-forward "^\n" nil t)
283         (delete-region (point-min) (match-end 0))
284       )
285     (setq major-mode 'mime/show-message-mode)
286     (setq mime::article/code-converter code-converter)
287     (mime/viewer-mode mother)
288     ))
289
290
291 ;;; @ message/partial
292 ;;;
293
294 (defvar mime-article/coding-system-alist
295   (and (boundp 'MULE)
296        '((mh-show-mode . *noconv*)
297          (t            . *ctext*)
298          )))             
299
300 (defvar mime-article/kanji-code-alist
301   (and (boundp 'NEMACS)
302        '((mh-show-mode . nil)
303          (t            . 2)
304          ))) 
305
306 (defun mime-article/decode-message/partial (beg end cal)
307   (goto-char beg)
308   (let* ((root-dir (expand-file-name
309                     (concat "m-prts-" (user-login-name)) mime/tmp-dir))
310          (id (cdr (assoc "id" cal)))
311          (number (cdr (assoc "number" cal)))
312          (total (cdr (assoc "total" cal)))
313          (the-buf (current-buffer))
314          file
315          (mother mime::article/preview-buffer)
316          (win-conf (save-excursion
317                      (set-buffer mother)
318                      mime::preview/original-window-configuration))
319          )
320     (if (not (file-exists-p root-dir))
321         (make-directory root-dir)
322       )
323     (setq id (replace-as-filename id))
324     (setq root-dir (concat root-dir "/" id))
325     (if (not (file-exists-p root-dir))
326         (make-directory root-dir)
327       )
328     (setq file (concat root-dir "/FULL"))
329     (if (not (file-exists-p file))
330         (progn
331           (re-search-forward "^$")
332           (goto-char (1+ (match-end 0)))
333           (setq file (concat root-dir "/" number))
334           (let ((file-coding-system
335                  (cdr
336                   (or (assq major-mode mime-article/coding-system-alist)
337                       (assq t mime-article/coding-system-alist)
338                       )))
339                 (kanji-fileio-code
340                  (cdr
341                   (or (assq major-mode mime-article/kanji-code-alist)
342                       (assq t mime-article/kanji-code-alist)
343                       )))
344                 )
345             (write-region (point) (point-max) file)
346             )
347           (if (get-buffer mime/temp-buffer-name)
348               (kill-buffer mime/temp-buffer-name)
349             )
350           (switch-to-buffer mime/temp-buffer-name)
351           (let ((i 1)
352                 (max (string-to-int total))
353                 (file-coding-system-for-read (if (boundp 'MULE)
354                                                  *noconv*))
355                 kanji-fileio-code)
356             (catch 'tag
357               (while (<= i max)
358                 (setq file (concat root-dir "/" (int-to-string i)))
359                 (if (not (file-exists-p file))
360                     (progn
361                       (switch-to-buffer the-buf)
362                       (throw 'tag nil)
363                       ))
364                 (insert-file-contents file)
365                 (goto-char (point-max))
366                 (setq i (1+ i))
367                 )
368               ;;(delete-other-windows)
369               (let ((buf (current-buffer)))
370                 (write-file (concat root-dir "/FULL"))
371                 (set-window-configuration win-conf)
372                 (let ((win (get-buffer-window mother)))
373                   (if win
374                       (select-window win)
375                     ))
376                 (set-window-buffer (selected-window) buf)
377                 ;;(set-window-buffer buf)
378                 (setq major-mode 'mime/show-message-mode)
379                 )
380               (mime/viewer-mode mother)
381               (pop-to-buffer (current-buffer))
382               ))
383           )
384       (progn
385         ;;(delete-other-windows)
386         (set-window-configuration win-conf)
387         (select-window (get-buffer-window mother))
388         (let ((file-coding-system-for-read
389                (if (boundp 'MULE) *noconv*))
390               kanji-fileio-code)
391           (set-buffer (get-buffer-create "FULL"))
392           (insert-file-contents file)
393           )
394         (setq major-mode 'mime/show-message-mode)
395         (mime/viewer-mode mother)
396         ;;(pop-to-buffer (current-buffer))
397         ))
398     ))
399
400
401 ;;; @ rot13-47
402 ;;;
403
404 (defun mime-article/decode-caesar (beg end cal)
405   (let* ((cnum (mime-article/point-content-number beg))
406          (cur-buf (current-buffer))
407          (new-name (format "%s-%s" (buffer-name) cnum))
408          (mother mime::article/preview-buffer)
409          (charset (cdr (assoc "charset" cal)))
410          (encoding (cdr (assq 'encoding cal)))
411          (mode major-mode)
412          str)
413     (setq str (buffer-substring beg end))
414     (switch-to-buffer new-name)
415     (setq buffer-read-only nil)
416     (erase-buffer)
417     (insert str)
418     (goto-char (point-min))
419     (if (re-search-forward "^\n" nil t)
420         (delete-region (point-min) (match-end 0))
421       )
422     (let ((m (assq mode mime-viewer/code-converter-alist)))
423       (if (and m (fboundp (setq m (cdr m))))
424           (funcall m (point-min) (point-max) charset encoding)
425         (mime-viewer/default-code-convert-region (point-min) (point-max)
426                                                  charset encoding)
427         ))
428     (save-excursion
429       (set-mark (point-min))
430       (goto-char (point-max))
431       (tm:caesar-region)
432       )
433     (view-mode)
434     ))
435
436
437 ;;; @ end
438 ;;;
439
440 (provide 'tm-play)
441
442 ;;; tm-play.el ends here