update.
[elisp/emh.git] / emh.el
1 ;;; emh.el --- MIME extender for mh-e
2
3 ;; Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc.
4
5 ;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
6 ;;         OKABE Yasuo <okabe@kudpc.kyoto-u.ac.jp>
7 ;; Maintainer: MORIOKA Tomohiko <morioka@jaist.ac.jp>
8 ;; Created: 1993/11/21
9 ;;      Renamed: 1993/11/27 from mh-e-mime.el
10 ;;      Renamed: 1997/02/21 from tm-mh-e.el
11 ;; Keywords: MH, MIME, multimedia, encoded-word, multilingual, mail
12
13 ;; This file is part of emh.
14
15 ;; This program is free software; you can redistribute it and/or
16 ;; modify it under the terms of the GNU General Public License as
17 ;; published by the Free Software Foundation; either version 2, or (at
18 ;; your option) any later version.
19
20 ;; This program is distributed in the hope that it will be useful, but
21 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23 ;; General Public License for more details.
24
25 ;; You should have received a copy of the GNU General Public License
26 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
27 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
28 ;; Boston, MA 02111-1307, USA.
29
30 ;;; Code:
31
32 (require 'mh-e)
33 (require 'alist)
34 (require 'mime-view)
35 (eval-when-compile (require 'mime-text))
36
37
38 ;;; @ version
39 ;;;
40
41 (defconst emh-version "1.6.1")
42
43
44 ;;; @ variable
45 ;;;
46
47 (defgroup emh nil
48   "MIME Extension for mh-e"
49   :group 'mime
50   :group 'mh)
51
52 (defcustom emh-automatic-mime-preview t
53   "*If non-nil, show MIME processed message."
54   :group 'emh
55   :type 'boolean)
56
57 (defcustom emh-decode-encoded-word t
58   "*If non-nil, decode encoded-word when it is not MIME preview mode."
59   :group 'emh
60   :type 'boolean)
61
62
63 ;;; @ functions
64 ;;;
65
66 (defun mh-display-msg (msg-num folder &optional show-buffer mode)
67   "Display message number MSG-NUM of FOLDER.
68 This function uses `mime-view-mode' if MODE is not nil.  If MODE is
69 nil, `emh-automatic-mime-preview' is used as default value."
70   (or mode
71       (setq mode emh-automatic-mime-preview)
72       )
73   ;; Display message NUMBER of FOLDER.
74   ;; Sets the current buffer to the show buffer.
75   (set-buffer folder)
76   (or show-buffer
77       (setq show-buffer mh-show-buffer))
78   ;; Bind variables in folder buffer in case they are local
79   (let ((msg-filename (mh-msg-filename msg-num)))
80     (if (not (file-exists-p msg-filename))
81         (error "Message %d does not exist" msg-num))
82     (set-buffer show-buffer)
83     (cond ((not (equal msg-filename buffer-file-name))
84            ;; Buffer does not yet contain message.
85            (clear-visited-file-modtime)
86            (unlock-buffer)
87            (setq buffer-file-name nil)  ; no locking during setup
88            (setq buffer-read-only nil)
89            (erase-buffer)
90            (if mode
91                (let* ((aname (concat "article-" folder))
92                       (abuf (get-buffer aname))
93                       )
94                  (if abuf
95                      (progn
96                        (set-buffer abuf)
97                        (setq buffer-read-only nil)
98                        (erase-buffer)
99                        )
100                    (setq abuf (get-buffer-create aname))
101                    (set-buffer abuf)
102                    (set-buffer-multibyte nil)
103                    )
104                  (insert-file-contents-as-raw-text msg-filename)
105                  (set-buffer-modified-p nil)
106                  (setq buffer-read-only t)
107                  (setq buffer-file-name msg-filename)
108                  (mh-show-mode)
109                  (mime-view-buffer aname (concat "show-" folder))
110                  (goto-char (point-min))
111                  )
112              (let ((clean-message-header mh-clean-message-header)
113                    (invisible-headers mh-invisible-headers)
114                    (visible-headers mh-visible-headers)
115                    )
116                ;; 1995/9/21
117                ;;   modified by ARIURA <ariura@cc.tuat.ac.jp>
118                ;;   to support mhl.
119                (if mhl-formfile
120                    (mh-exec-lib-cmd-output "mhl" "-nobell" "-noclear"
121                                            (if (stringp mhl-formfile)
122                                                (list "-form" mhl-formfile))
123                                            msg-filename)
124                  (insert-file-contents msg-filename))
125                ;; end
126                (goto-char (point-min))
127                (cond (clean-message-header
128                       (mh-clean-msg-header (point-min)
129                                            invisible-headers
130                                            visible-headers)
131                       (goto-char (point-min)))
132                      (t
133                       (mh-start-of-uncleaned-message)))
134                (if emh-decode-encoded-word
135                    (eword-decode-header)
136                  )
137                (set-buffer-modified-p nil)
138                (setq buffer-read-only t)
139                (setq buffer-file-name msg-filename)
140                (mh-show-mode)
141                ))
142            (or (eq buffer-undo-list t)  ;don't save undo info for prev msgs
143                (setq buffer-undo-list nil))
144 ;;; Added by itokon (02/19/96)
145            (setq buffer-file-name msg-filename)
146 ;;;
147            (set-mark nil)
148            (setq mode-line-buffer-identification
149                  (list (format mh-show-buffer-mode-line-buffer-id
150                                folder msg-num)))
151            (set-buffer folder)
152            (setq mh-showing-with-headers nil)))))
153
154 (defun emh-view-message (&optional msg)
155   "MIME decode and play this message."
156   (interactive)
157   (if (or (null emh-automatic-mime-preview)
158           (null (get-buffer mh-show-buffer))
159           (save-excursion
160             (set-buffer mh-show-buffer)
161             (not (eq major-mode 'mime-view-mode))
162             ))
163       (let ((emh-automatic-mime-preview t))
164         (mh-invalidate-show-buffer)
165         (mh-show-msg msg)
166         ))
167   (pop-to-buffer mh-show-buffer)
168   )
169
170 (defun emh-toggle-decoding-mode (arg)
171   "Toggle MIME processing mode.
172 With arg, turn MIME processing on if arg is positive."
173   (interactive "P")
174   (setq emh-automatic-mime-preview
175         (if (null arg)
176             (not emh-automatic-mime-preview)
177           arg))
178   (save-excursion
179     (set-buffer mh-show-buffer)
180     (if (null emh-automatic-mime-preview)
181         (if (and mime-raw-buffer
182                  (get-buffer mime-raw-buffer))
183             (kill-buffer mime-raw-buffer)
184           )))
185   (mh-invalidate-show-buffer)
186   (mh-show (mh-get-msg-num t))
187   )
188
189 (defun emh-show (&optional message)
190   (interactive)
191   (mh-invalidate-show-buffer)
192   (mh-show message)
193   )
194
195 (defun emh-header-display ()
196   (interactive)
197   (mh-invalidate-show-buffer)
198   (let (mime-view-ignored-field-list
199         mime-view-visible-field-list
200         emh-decode-encoded-word)
201     (mh-header-display)
202     ))
203
204 (defun emh-raw-display ()
205   (interactive)
206   (mh-invalidate-show-buffer)
207   (let (emh-automatic-mime-preview
208         emh-decode-encoded-word)
209     (mh-header-display)
210     ))
211
212 (defun emh-burst-multipart/digest ()
213   "Burst apart the current message, which should be a multipart/digest.
214 The message is replaced by its table of contents and the letters from the
215 digest are inserted into the folder after that message."
216   (interactive)
217   (let ((digest (mh-get-msg-num t)))
218     (mh-process-or-undo-commands mh-current-folder)
219     (mh-set-folder-modified-p t)                ; lock folder while bursting
220     (message "Bursting digest...")
221     (mh-exec-cmd "mhn" "-store" mh-current-folder digest)
222     (mh-scan-folder mh-current-folder (format "%d-last" mh-first-msg-num))
223     (message "Bursting digest...done")
224     ))
225
226
227 ;;; @ for mime-view
228 ;;;
229
230 (set-alist 'mime-raw-representation-type-alist 'mh-show-mode 'binary)
231
232
233 (defvar emh-display-header-hook (if window-system
234                                     '(emh-highlight-header)
235                                   )
236   "Hook for header filtering.")
237
238 (autoload 'emh-highlight-header "emh-face")
239
240 (defun emh-header-presentation-method (entity situation)
241   (mime-insert-decoded-header
242    entity
243    mime-view-ignored-field-list mime-view-visible-field-list
244    default-mime-charset)
245   (run-hooks 'emh-display-header-hook)
246   )
247
248 (set-alist 'mime-header-presentation-method-alist
249            'mh-show-mode #'emh-header-presentation-method)
250
251
252 (defun emh-quitting-method ()
253   (let ((buf (current-buffer)))
254     (mime-maybe-hide-echo-buffer)
255     (pop-to-buffer
256      (let ((name (buffer-name buf)))
257        (substring name 5)
258        ))
259     (if (not emh-automatic-mime-preview)
260         (mh-invalidate-show-buffer)
261       )
262     (mh-show (mh-get-msg-num t))
263     ))
264
265 (set-alist 'mime-preview-quitting-method-alist
266            'mh-show-mode #'emh-quitting-method)
267
268
269 (defun emh-following-method (buf)
270   (save-excursion
271     (set-buffer buf)
272     (goto-char (point-max))
273     (setq mh-show-buffer buf)
274     (apply (function mh-send)
275            (std11-field-bodies '("From" "cc" "Subject") ""))
276     (setq mh-sent-from-folder buf)
277     (setq mh-sent-from-msg 1)
278     (let ((last (point)))
279       (mh-yank-cur-msg)
280       (goto-char last)
281       )))
282
283 (set-alist 'mime-preview-following-method-alist
284            'mh-show-mode #'emh-following-method)
285
286
287 ;;; @@ for mime-partial
288 ;;;
289
290 (autoload 'mime-combine-message/partial-pieces-automatically
291   "mime-partial"
292   "Internal method to combine message/partial messages automatically.")
293
294 (mime-add-condition
295  'action
296  '((type . message)(subtype . partial)
297    (method . mime-combine-message/partial-pieces-automatically)
298    (major-mode . mh-show-mode)
299    (summary-buffer-exp
300     . (and (or (string-match "^article-\\(.+\\)$"
301                              article-buffer)
302                (string-match "^show-\\(.+\\)$" article-buffer))
303            (substring article-buffer
304                       (match-beginning 1) (match-end 1))
305            ))
306    ))
307
308 (set-alist 'mime-view-partial-message-method-alist
309            'mh-show-mode
310            (function
311             (lambda ()
312               (let ((emh-automatic-mime-preview t))
313                 (emh-show)
314                 ))))
315
316
317 ;;; @ set up
318 ;;;
319
320 (define-key mh-folder-mode-map "v" (function emh-view-message))
321 (define-key mh-folder-mode-map "\et" (function emh-toggle-decoding-mode))
322 (define-key mh-folder-mode-map "." (function emh-show))
323 (define-key mh-folder-mode-map "," (function emh-header-display))
324 (define-key mh-folder-mode-map "\e," (function emh-raw-display))
325 (define-key mh-folder-mode-map "\C-c\C-b"
326   (function emh-burst-multipart/digest))
327
328 (defun emh-summary-before-quit ()
329   (let ((buf (get-buffer mh-show-buffer)))
330     (if buf
331         (let ((the-buf (current-buffer)))
332           (switch-to-buffer buf)
333           (if (and mime-preview-buffer
334                    (setq buf (get-buffer mime-preview-buffer))
335                    )
336               (progn
337                 (switch-to-buffer the-buf)
338                 (kill-buffer buf)
339                 )
340             (switch-to-buffer the-buf)
341             )
342           ))))
343
344 (add-hook 'mh-before-quit-hook (function emh-summary-before-quit))
345
346
347 ;;; @ for BBDB
348 ;;;
349
350 (eval-after-load "bbdb" '(require 'mime-bbdb))
351
352
353 ;;; @ end
354 ;;;
355
356 (provide 'emh)
357
358 (run-hooks 'emh-load-hook)
359
360 ;;; emh.el ends here