Fix typo.
[elisp/wanderlust.git] / elmo / mmelmo.el
1 ;;; mmelmo.el -- mm-backend by ELMO.
2
3 ;; Copyright (C) 1998,1999,2000 Yuuichi Teranishi <teranisi@gohome.org>
4
5 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
6 ;; Keywords: mail, net news
7
8 ;; This file is part of ELMO (Elisp Library for Message Orchestration).
9
10 ;; This program is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14 ;;
15 ;; This program is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;; GNU General Public License for more details.
19 ;;
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24 ;;
25
26 ;;; Commentary:
27 ;; 
28
29 ;;; Code:
30 ;; 
31 (require 'elmo-vars)
32 (require 'elmo-util)
33 (require 'mime-parse)
34 (require 'mmbuffer)
35
36 (provide 'mmelmo)                       ; circular dependency
37 (require 'mmelmo-imap4)
38
39 (eval-and-compile
40   (luna-define-class mime-elmo-entity (mime-buffer-entity)
41                      (imap folder number msgdb size))
42   (luna-define-internal-accessors 'mime-elmo-entity))
43
44 (defvar mmelmo-force-reload nil)
45 (defvar mmelmo-sort-field-list nil)
46
47 (defvar mmelmo-header-max-column fill-column
48   "*Inserted header is folded with this value.
49 If function is specified, its return value is used.")
50
51 (defvar mmelmo-header-inserted-hook nil
52   "*A hook called when header is inserted.")
53
54 (defvar mmelmo-entity-content-inserted-hook nil
55   "*A hook called when entity-content is inserted.")
56
57 (defun mmelmo-get-original-buffer ()
58   (let ((ret-val (get-buffer (concat mmelmo-entity-buffer-name "0"))))
59     (if (not ret-val)
60         (save-excursion
61           (set-buffer (setq ret-val
62                             (get-buffer-create
63                              (concat mmelmo-entity-buffer-name "0"))))
64           (mmelmo-original-mode)))
65     ret-val))
66
67 (defun mmelmo-cleanup-entity-buffers ()
68   "Cleanup entity buffers of mmelmo."
69   (mapcar (lambda (x)
70             (if (string-match mmelmo-entity-buffer-name x)
71                 (kill-buffer x)))
72           (mapcar 'buffer-name (buffer-list))))
73
74 ;; For FLIM 1-13.x
75 (defun-maybe mime-entity-body (entity)
76   (luna-send entity 'mime-entity-body))
77
78 (defun mmelmo-insert-sorted-header-from-buffer (buffer
79                                                 start end
80                                                 &optional invisible-fields
81                                                 visible-fields
82                                                 sorted-fields)
83   (let ((the-buf (current-buffer))
84         (mode-obj (mime-find-field-presentation-method 'wide))
85         field-decoder
86         f-b p f-e field-name field field-body
87         vf-alist (sl sorted-fields))
88     (save-excursion
89       (set-buffer buffer)
90       (save-restriction
91         (narrow-to-region start end)
92         (goto-char start)
93         (while (re-search-forward std11-field-head-regexp nil t)
94           (setq f-b (match-beginning 0)
95                 p (match-end 0)
96                 field-name (buffer-substring f-b p)
97                 f-e (std11-field-end))
98           (when (mime-visible-field-p field-name
99                                       visible-fields invisible-fields)
100             (setq field (intern
101                          (capitalize (buffer-substring f-b (1- p))))
102                   field-body (buffer-substring p f-e)
103                   field-decoder (inline (mime-find-field-decoder-internal
104                                          field mode-obj)))
105             (setq vf-alist (append (list
106                                     (cons field-name
107                                           (list field-body field-decoder)))
108                                    vf-alist))))
109         (and vf-alist
110              (setq vf-alist
111                    (sort vf-alist
112                          (function (lambda (s d)
113                                      (let ((n 0) re
114                                            (sf (car s))
115                                            (df (car d)))
116                                        (catch 'done
117                                          (while (setq re (nth n sl))
118                                            (setq n (1+ n))
119                                            (and (string-match re sf)
120                                                 (throw 'done t))
121                                            (and (string-match re df)
122                                                 (throw 'done nil)))
123                                          t)))))))
124         (with-current-buffer the-buf
125           (while vf-alist
126             (let* ((vf (car vf-alist))
127                    (field-name (car vf))
128                    (field-body (car (cdr vf)))
129                    (field-decoder (car (cdr (cdr vf)))))
130               (insert field-name)
131               (insert (if field-decoder
132                           (funcall field-decoder field-body
133                                    (string-width field-name)
134                                    (if (functionp mmelmo-header-max-column)
135                                        (funcall mmelmo-header-max-column)
136                                      mmelmo-header-max-column))
137                         ;; Don't decode
138                         field-body))
139               (insert "\n"))
140             (setq vf-alist (cdr vf-alist)))
141           (run-hooks 'mmelmo-header-inserted-hook))))))
142
143 (defun mmelmo-original-mode ()
144   (setq major-mode 'mmelmo-original-mode)
145   (setq buffer-read-only t)
146   (elmo-set-buffer-multibyte nil)
147   (setq mode-name "MMELMO-Original"))
148
149 ;; For FLIMs without rfc2231 feature .
150 (if (not (fboundp 'mime-parse-parameters-from-list))
151     (defun mime-parse-parameters-from-list (attrlist)
152       (let (ret-val)
153         (if (not (eq (% (length attrlist) 2) 0))
154             (message "Invalid attributes."))
155         (while attrlist
156           (setq ret-val (append ret-val
157                                 (list (cons (downcase (car attrlist))
158                                             (car (cdr attrlist))))))
159           (setq attrlist (cdr (cdr attrlist))))
160         ret-val)))
161
162 (luna-define-method initialize-instance :after ((entity mime-elmo-entity)
163                                                 &rest init-args)
164   "The initialization method for elmo.
165 mime-elmo-entity has its own member variable,
166 `imap', `folder', `msgdb' and `size'.
167 imap:   boolean. if non-nil, entity becomes mime-elmo-imap4-entity class.
168 folder: string.  folder name.
169 msgdb:  msgdb of elmo.
170 size:   size of the entity."
171   (if (mime-elmo-entity-imap-internal entity)
172       ;; use imap part fetching.
173       ;; child mime-entity's class becomes `mime-elmo-imap4-entity'
174       ;; which implements `entity-buffer' method.
175       (progn
176         (let (new-entity)
177           (mime-buffer-entity-set-buffer-internal entity nil)
178           (setq new-entity
179                 (mmelmo-imap4-get-mime-entity
180                  (mime-elmo-entity-folder-internal entity) ; folder
181                  (mime-elmo-entity-number-internal entity) ; number
182                  (mime-elmo-entity-msgdb-internal entity)  ; msgdb
183                  ))
184           (mime-entity-set-content-type-internal
185            entity
186            (mime-entity-content-type-internal new-entity))
187           (mime-entity-set-encoding-internal
188            entity
189            (mime-entity-encoding-internal new-entity))
190           (mime-entity-set-children-internal
191            entity
192            (mime-entity-children-internal new-entity))
193           (mime-elmo-entity-set-size-internal
194            entity
195            (mime-elmo-entity-size-internal new-entity))
196           (mime-entity-set-representation-type-internal
197            entity 'mime-elmo-imap4-entity)
198           entity))
199     (set-buffer (mime-buffer-entity-buffer-internal entity))
200     (mmelmo-original-mode)
201     (when (mime-root-entity-p entity)
202       (let ((buffer-read-only nil)
203             header-end body-start)
204         (erase-buffer)
205         (elmo-read-msg-with-buffer-cache
206          (mime-elmo-entity-folder-internal entity)
207          (mime-elmo-entity-number-internal entity)
208          (current-buffer)
209          (mime-elmo-entity-msgdb-internal entity)
210          mmelmo-force-reload)
211         (goto-char (point-min))
212         (if (re-search-forward
213              (concat "^" (regexp-quote mail-header-separator) "$\\|^$" )
214              nil t)
215             (setq header-end (match-beginning 0)
216                   body-start (if (= (match-end 0) (point-max))
217                                  (point-max)
218                                (1+ (match-end 0))))
219           (setq header-end (point-min)
220                 body-start (point-min)))
221         (mime-buffer-entity-set-header-start-internal entity (point-min))
222         (mime-buffer-entity-set-header-end-internal entity header-end)
223         (mime-buffer-entity-set-body-start-internal entity body-start)
224         (mime-buffer-entity-set-body-end-internal entity (point-max))
225         (save-restriction
226           (narrow-to-region (mime-buffer-entity-header-start-internal entity)
227                             (mime-buffer-entity-header-end-internal entity))
228           (mime-entity-set-content-type-internal
229            entity
230            (let ((str (std11-fetch-field "Content-Type")))
231              (if str
232                  (mime-parse-Content-Type str)
233                ))))))
234     entity))
235
236 (luna-define-method mime-insert-header ((entity mime-elmo-entity)
237                                         &optional invisible-fields
238                                         visible-fields)
239   (mmelmo-insert-sorted-header-from-buffer
240    (mime-buffer-entity-buffer-internal entity)
241    (mime-buffer-entity-header-start-internal entity)
242    (mime-buffer-entity-header-end-internal entity)
243    invisible-fields visible-fields mmelmo-sort-field-list))
244
245 (luna-define-method mime-insert-text-content :around ((entity
246                                                        mime-elmo-entity))
247   (luna-call-next-method)
248   (run-hooks 'mmelmo-entity-content-inserted-hook))
249
250 (luna-define-method mime-entity-body ((entity mime-elmo-entity))
251   (with-current-buffer (mime-buffer-entity-buffer-internal entity)
252     (buffer-substring (mime-buffer-entity-body-start-internal entity)
253                       (mime-buffer-entity-body-end-internal entity))))
254
255 ;;(luna-define-method mime-entity-content ((entity mime-elmo-entity))
256 ;;  (mime-decode-string
257 ;;   (with-current-buffer (mime-buffer-entity-buffer-internal entity)
258 ;;     (buffer-substring (mime-buffer-entity-body-start-internal entity)
259 ;;                     (mime-buffer-entity-body-end-internal entity)))
260 ;;   (mime-entity-encoding entity)))
261
262 (require 'product)
263 (product-provide (provide 'mmelmo) (require 'elmo-version))
264
265 ;;; mmelmo.el ends here