1 ;;; mew-draft.el --- Draft mode for Mew
3 ;; Author: Kazu Yamamoto <Kazu@Mew.org>
4 ;; Created: Oct 2, 1996
5 ;; Revised: Sep 3, 1999
9 (defconst mew-draft-version "mew-draft.el version 0.36")
13 (unless (fboundp 'read-event)
14 (defsubst read-event (&optional prompt)
15 (aref (read-key-sequence prompt) 0)))
17 (if mew-xemacs-p (require 'easymenu))
19 (defvar mew-draft-mode-map nil)
20 (defvar mew-draft-header-map nil)
21 (defvar mew-draft-body-map nil)
23 (defvar mew-draft-mode-syntax-table nil
24 "*Syntax table used while in Draft mode.")
26 (if mew-draft-mode-syntax-table
28 (setq mew-draft-mode-syntax-table (make-syntax-table text-mode-syntax-table))
29 (modify-syntax-entry ?% "." mew-draft-mode-syntax-table))
31 (defvar mew-draft-mode-toolbar-menu
32 '("Attachment Commands"
33 ["Insert a File by Linking"
35 (mew-attach-not-line012-1)]
36 ["Insert a File by Copying"
38 (mew-attach-not-line012-1)]
41 (mew-attach-not-line012-1)]
42 ["Insert an External Reference"
43 mew-attach-external-body
44 (mew-attach-not-line012-1)]
45 ["Insert a Sub-Multipart"
47 (mew-attach-not-line012-1)]
48 ["Read a New File into a Buffer"
49 mew-attach-find-new-file
50 (mew-attach-not-line012-1)]
51 ["Insert PGP public keys"
52 mew-attach-pgp-public-key
53 (mew-attach-not-line012-1)]
57 (mew-attach-not-line012-1-dot)]
60 mew-attach-description
61 (mew-attach-not-line0-1-dot)]
62 ["Specify A File Name"
63 mew-attach-disposition
64 (mew-attach-not-line012-1-dot)]
67 (mew-attach-not-line0-1-dot)]
70 (mew-attach-not-line0-1-dot)]
73 (mew-attach-not-line0-1-dot)]
74 ["Encode with Quoted-Printable"
75 mew-attach-quoted-printable
76 (mew-attach-not-line0-1-dot)]
79 (mew-attach-not-line0-1-dot)]
82 (mew-attach-not-line0-1-dot)]
86 (mew-attach-not-line0-1-dot)]
88 ["Read This File into a Buffer"
90 (mew-attach-not-line012-1-dot)]
94 (defvar mew-draft-mode-menu-spec
97 ["Cite" mew-draft-cite t]
98 ["Cite without Label" mew-draft-yank t]
99 ["Insert Config:" mew-draft-insert-config t]
100 mew-draft-mode-toolbar-menu
101 ["Make MIME Message" mew-draft-make-message (mew-header-p)]
102 ["Send Message" mew-draft-send-letter (not (mew-header-p))]
103 ["Prepare Attachments" mew-draft-prepare-attachments (and (mew-header-p) (not (mew-attach-p)))]
104 ["Insert Signature" mew-draft-insert-signature t]
105 ["Kill Draft" mew-draft-kill t]
108 ["PGP Sign" mew-pgp-sign-letter (mew-header-p)]
109 ["PGP Encrypt" mew-pgp-encrypt-letter (mew-header-p)]
110 ["PGP Sign then Encrypt" mew-pgp-sign-encrypt-letter (mew-header-p)]
111 ["PGP Encrypt then Sign" mew-pgp-encrypt-sign-letter (mew-header-p)])
113 ["All messages" mew-draft-toggle-privacy-always t]
114 ["Msgs replying to encrypted" mew-draft-toggle-privacy-encrypted t]
115 ["This message" mew-draft-set-privacy-type t])
117 ["FIB next item" mew-fib-next-item (not (mew-attach-p))]
118 ["FIB previous item" mew-fib-previous-item (not (mew-attach-p))]
119 ["FIB flush input" mew-fib-flush-input (not (mew-attach-p))]
120 ["FIB fill default" mew-fib-fill-default (not (mew-attach-p))]
121 ["FIB delete frame" mew-fib-delete-frame (not (mew-attach-p))])))
123 (if mew-draft-header-map
125 (setq mew-draft-header-map (make-sparse-keymap))
126 (define-key mew-draft-header-map "\t" 'mew-draft-header-comp)
127 (define-key mew-draft-header-map "\C-c\t" 'mew-draft-circular-comp)
128 (define-key mew-draft-header-map "\e\t" 'mew-draft-expand))
131 (mew-use-overlay-keymap
132 (defun mew-draft-share-keymap (symmap)
133 (define-key (symbol-value symmap) "\C-c\C-m" 'mew-draft-make-message)
134 (define-key (symbol-value symmap) "\C-c\C-c" 'mew-draft-send-letter)
135 (define-key (symbol-value symmap) "\C-c\C-a" 'mew-draft-prepare-attachments)
136 (define-key (symbol-value symmap) "\C-c\C-o" 'mew-draft-insert-config)
137 (define-key (symbol-value symmap) "\C-c\C-l" 'mew-draft-rehighlight)
138 (define-key (symbol-value symmap) "\C-c\C-u" 'mew-draft-undo)
139 (define-key (symbol-value symmap) "\C-c\C-q" 'mew-draft-kill)
140 (define-key (symbol-value symmap) "\C-c\C-s" 'mew-pgp-sign-letter)
141 (define-key (symbol-value symmap) "\C-c\C-e" 'mew-pgp-encrypt-letter)
142 (define-key (symbol-value symmap) "\C-c\C-b" 'mew-pgp-sign-encrypt-letter)
143 (define-key (symbol-value symmap) "\C-c\C-r" 'mew-pgp-encrypt-sign-letter)
144 (define-key (symbol-value symmap) "\C-c\C-p\C-a" 'mew-draft-toggle-privacy-always)
145 (define-key (symbol-value symmap) "\C-c\C-p\C-e" 'mew-draft-toggle-privacy-encrypted)
146 (define-key (symbol-value symmap) "\C-c\C-p\C-d" 'mew-draft-set-privacy-type)
147 (define-key (symbol-value symmap) "\C-x\C-s" 'mew-save-buffer))
148 (if mew-draft-body-map
150 (setq mew-draft-body-map (make-sparse-keymap))
151 (mew-set-keymap-parent mew-draft-body-map text-mode-map)
152 (define-key mew-draft-body-map "\C-c\t" 'mew-draft-insert-signature)
153 (define-key mew-draft-body-map "\C-c\C-y" 'mew-draft-cite)
154 (define-key mew-draft-body-map "\C-c\C-t" 'mew-draft-yank)
155 (define-key mew-draft-body-map "\C-c\C-f\C-f" 'mew-fib-fill-default)
156 (define-key mew-draft-body-map "\C-c\C-f\C-k" 'mew-fib-delete-frame)
157 (define-key mew-draft-body-map "\C-c\C-f\C-n" 'mew-fib-next-item)
158 (define-key mew-draft-body-map "\C-c\C-f\C-p" 'mew-fib-previous-item)
159 (define-key mew-draft-body-map "\C-c\C-f\C-z" 'mew-fib-flush-input)
160 (mew-draft-share-keymap 'mew-draft-body-map))
161 (mew-draft-share-keymap 'mew-draft-header-map)
162 (if mew-draft-mode-map
164 (setq mew-draft-mode-map (make-sparse-keymap))
165 (set-keymap-parent mew-draft-mode-map mew-draft-body-map)))
167 (defun mew-draft-keyswitch ()
168 "A function to implement region key binding."
170 (let ((key (this-command-keys))
171 command func len (i 0))
172 (if (and mew-xemacs-p (= (length key) 0))
173 (setq key (vector last-command-event)))
174 (setq command (lookup-key (current-global-map) key))
175 (if (numberp command)
177 command (lookup-key (current-global-map)
178 (mew-subsequence key 0 len))
179 key (mew-subsequence key len)))
180 (setq len (length key))
181 (if (or (eq command 'universal-argument) (eq command 'digit-argument))
183 (while (and (or (eq command 'universal-argument)
184 (eq command 'digit-argument))
185 (let ((tmp (aref key i)))
186 (if mew-xemacs-p (setq tmp (event-to-character tmp)))
187 (and (<= ?0 tmp) (>= ?9 tmp))))
190 (if (eq 'mew-draft-keyswitch
191 (key-binding (char-to-string (aref key i))))
192 (throw 'keyswitch (setq key (mew-subsequence key i))))
196 (setq func (lookup-key mew-draft-attach-map key)))
198 (setq func (lookup-key mew-draft-header-map key)))
200 (setq func (lookup-key mew-draft-body-map key))))
201 (if (not (integerp func))
203 (setq key (mew-subsequence key 0 func))
204 (setq func (lookup-key (current-global-map) key))
207 (setq func (lookup-key mew-draft-attach-map key)))
209 (setq func (lookup-key mew-draft-header-map key)))
211 (setq func (lookup-key mew-draft-body-map key)))))
214 (setq func (lookup-key (current-global-map) key))
215 (if (not (integerp func))
217 (setq key (mew-subsequence key 0 func))
218 (setq func (lookup-key (current-global-map) key))))
220 (while (keymapp func)
222 (setq key (vconcat key (read-event)))
223 (setq key (concat key (char-to-string (read-event)))))
224 (setq func (lookup-key (current-global-map) key))))
226 (insert key) ;; just in case
227 (setq this-command func)
228 (run-hooks 'pre-command-hook)
229 (call-interactively this-command))))
230 (if mew-draft-body-map
232 (setq mew-draft-body-map (make-sparse-keymap))
233 (define-key mew-draft-body-map "\C-c\t" 'mew-draft-insert-signature))
234 (if mew-draft-mode-map
236 (setq mew-draft-mode-map (make-sparse-keymap))
237 (let ((begin ?\40) (end ?\177))
238 (while (<= begin end)
239 (define-key mew-draft-mode-map
240 (char-to-string begin) 'mew-draft-keyswitch)
241 (setq begin (1+ begin))))
242 (define-key mew-draft-mode-map "\C-m" 'mew-draft-keyswitch)
243 (define-key mew-draft-mode-map "\C-n" 'mew-draft-keyswitch)
244 (define-key mew-draft-mode-map "\C-p" 'mew-draft-keyswitch)
245 (define-key mew-draft-mode-map "\C-f" 'mew-draft-keyswitch)
246 (define-key mew-draft-mode-map "\C-b" 'mew-draft-keyswitch)
247 (define-key mew-draft-mode-map "\t" 'mew-draft-keyswitch)
248 (define-key mew-draft-mode-map "\e\t" 'mew-draft-keyswitch)
249 (define-key mew-draft-mode-map "\C-c\t" 'mew-draft-keyswitch)
250 (define-key mew-draft-mode-map "\C-d" 'mew-draft-keyswitch)
251 (define-key mew-draft-mode-map "\C-o" 'mew-draft-keyswitch)
252 (define-key mew-draft-mode-map "\C-q" 'mew-draft-keyswitch)
253 (define-key mew-draft-mode-map "\C-t" 'mew-draft-keyswitch)
254 (define-key mew-draft-mode-map "\C-w" 'mew-draft-keyswitch)
255 (define-key mew-draft-mode-map "\C-k" 'mew-draft-keyswitch)
256 (define-key mew-draft-mode-map "\r" 'mew-draft-keyswitch)
257 (define-key mew-draft-mode-map "\n" 'mew-draft-keyswitch)
258 (define-key mew-draft-mode-map "\C-y" 'mew-draft-keyswitch)
259 (define-key mew-draft-mode-map "\C-c\C-d" 'mew-draft-keyswitch)
260 (define-key mew-draft-mode-map "\C-c\C-r" 'mew-draft-keyswitch)
261 (define-key mew-draft-mode-map "\C-c\C-y" 'mew-draft-cite)
262 (define-key mew-draft-mode-map "\C-c\C-t" 'mew-draft-yank)
263 (define-key mew-draft-mode-map "\C-c\C-l" 'mew-draft-rehighlight)
264 (define-key mew-draft-mode-map "\C-c\C-m" 'mew-draft-make-message)
265 (define-key mew-draft-mode-map "\C-c\C-u" 'mew-draft-undo)
266 (define-key mew-draft-mode-map "\C-c\C-c" 'mew-draft-send-letter)
267 (define-key mew-draft-mode-map "\C-c\C-s" 'mew-pgp-sign-letter)
268 (define-key mew-draft-mode-map "\C-c\C-e" 'mew-pgp-encrypt-letter)
269 (define-key mew-draft-mode-map "\C-c\C-b" 'mew-pgp-sign-encrypt-letter)
270 (define-key mew-draft-mode-map "\C-c\C-r" 'mew-pgp-encrypt-sign-letter)
271 (define-key mew-draft-mode-map "\C-c\C-p\C-a" 'mew-draft-toggle-privacy-always)
272 (define-key mew-draft-mode-map "\C-c\C-p\C-e" 'mew-draft-toggle-privacy-encrypted)
273 (define-key mew-draft-mode-map "\C-c\C-p\C-d" 'mew-draft-set-privacy-type)
274 (define-key mew-draft-mode-map "\C-c\C-q" 'mew-draft-kill)
275 (define-key mew-draft-mode-map "\C-c\C-a" 'mew-draft-prepare-attachments)
276 (define-key mew-draft-mode-map "\C-c\C-f\C-f" 'mew-fib-fill-default)
277 (define-key mew-draft-mode-map "\C-c\C-f\C-k" 'mew-fib-delete-frame)
278 (define-key mew-draft-mode-map "\C-c\C-f\C-n" 'mew-fib-next-item)
279 (define-key mew-draft-mode-map "\C-c\C-f\C-p" 'mew-fib-previous-item)
280 (define-key mew-draft-mode-map "\C-c\C-f\C-z" 'mew-fib-flush-input)
281 (define-key mew-draft-mode-map "\C-c\C-o" 'mew-draft-insert-config)
282 (define-key mew-draft-mode-map "\C-x\C-s" 'mew-save-buffer)
290 "Menu used in Draft mode."
291 mew-draft-mode-menu-spec)
292 (if mew-use-overlay-keymap
294 mew-draft-header-menu
296 "Menu used in Draft mode."
297 mew-draft-mode-menu-spec)))
299 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
304 (defvar mew-draft-encrypted-p nil)
305 (defvar mew-draft-privacy-error nil)
306 (defvar mew-draft-protect-privacy-type nil)
308 (defun mew-draft-mode (&optional encrypted)
309 "\\<mew-draft-mode-map>
310 Mew Draft mode:: major mode for composing a MIME message.
311 Key actions are different in each region: Header, Body, and Attachment.
313 To send a draft, type \\[mew-draft-make-message] and \\[mew-draft-send-letter]. To make multipart, type
314 \\[mew-draft-prepare-attachments], edit attachments, type \\[mew-draft-make-message] and \\[mew-draft-send-letter].
316 *Whole buffer key assignment:
318 \\[mew-draft-make-message] Make a MIME message. Charset guess, mapping directory structure
319 to multipart, and so on.
320 \\[mew-draft-send-letter] Send this message. If you skipped '\\[mew-draft-make-message]', the header was
321 modified and you are asked, \"The header was modified.
322 Send this message? \". Type y or n. Mew sends the message
323 in background. So, when you exit Emacs, you may be asked,
324 \"Active processes exist; kill them and exit anyway? (yes or no)\".
325 In this case, check if *mew watch* buffer exist. If so, never
326 exit Emacs because Mew is still sending the message.
327 If executed \\[universal-argument], send this message
328 without killing the draft. This is convenient
329 to send messages to multiple people modifying the draft.
331 \\[mew-draft-prepare-attachments] Prepare an attachment region in the bottom of the draft.
332 To compose a multipart message, you should execute this
335 \\[mew-draft-insert-config] Insert the Config: field with 'mew-config-guess-alist'
337 \\[mew-draft-rehighlight] Highlight header and body again.
339 \\[mew-draft-undo] Undo '\\[mew-draft-make-message]'.
340 \\[mew-draft-kill] Kill this draft.
342 \\[mew-pgp-sign-letter] Sign the entire draft with PGP. Input your passphrase.
343 \\[mew-pgp-encrypt-letter] Encrypt the entire draft with PGP.
344 \\[mew-pgp-sign-encrypt-letter] Sign then encrypt the entire draft with PGP.
345 Input your passphrase.
346 \\[mew-pgp-encrypt-sign-letter] Encrypt then sign the entire draft with PGP.
347 Input your passphrase.
349 \\[mew-draft-toggle-privacy-always] Toggle whether or not all drafts are protected.
350 \\[mew-draft-toggle-privacy-encrypted] Toggle whether or not drafts replying to encrypted messages
352 \\[mew-draft-set-privacy-type] Set privacy service which will be effective when \\[mew-draft-make-message].
353 \\<mew-draft-header-map>
354 *Header region key assignment:
356 \\[mew-draft-header-comp] Complete field keys.
357 Complete and expand an address short name.
358 Complete folder names.
359 \\[mew-draft-circular-comp] Complete your mail domain.
360 \\[mew-draft-expand] Replace an address with 'NAME <address>'.
362 *Body region key assignment:
364 \\<mew-draft-body-map>\\[mew-draft-insert-signature] Insert '~/.signature' on the cursor point.
365 \\<mew-draft-mode-map>\\[mew-draft-cite] Copy and paste a part of message from Message mode WITH
366 citation prefix and label.
367 1. Roughly speaking, it copies the body in Message mode.
368 For example, if text/plain is displayed, the entire Message
369 mode is copied. If message/rfc822 is displayed, the body
370 without the header is copied.
371 2. If called with '\\[universal-argument]', the header is also copied if exists.
372 3. If an Emacs mark exists, the target is the region between
373 the mark and the cursor.
374 \\[mew-draft-yank] Copy and paste a part of message from Message mode WITHOUT
375 citation prefix and label.
377 *Attachments region Key assignment:
378 \\<mew-draft-attach-map>
379 \\[mew-attach-forward] Go to the first subdirectory.
380 \\[mew-attach-backforward] Go to the parent directory.
381 \\[mew-attach-next] Go to the next file in the current directory.
382 \\[mew-attach-previous] Go to the previous file in the current directory.
384 \\[mew-attach-copy] Copy a file (via networks) on '.'.
385 To copy a remote file, use the '/[user@]hostname:/filepath' syntax.
386 \\[mew-attach-link] Link a file with a symbolic link on '.'.
387 \\[mew-attach-delete] Delete this file or this directory.
388 \\[mew-attach-multipart] Create a subdirectory(i.e. multipart) on '.'.
389 \\[mew-attach-find-file] Open this file into a buffer.
390 \\[mew-attach-find-new-file] Open a new file into a buffer on '.'.
391 \\[mew-attach-external-body] Input external-body on '.'.
392 \\[mew-attach-audio] Sampling voice and insert as audio file on '.'.
393 \\[mew-attach-pgp-public-key] Extract the PGP key for the inputed user on '.'.
394 \\[mew-attach-description] Input a description(Content-Description:).
395 \\[mew-attach-disposition] Change the file name(Content-Disposition:).
396 \\[mew-attach-type] Change the data type(Content-Type:).
397 \\[mew-attach-charset] Specify charset for a Text/* object.
399 \\[mew-attach-base64] Put the 'B' mark to encode with Base64.
400 \\[mew-attach-quoted-printable] Put the 'Q' mark to encode with Quoted-Printable.
401 \\[mew-attach-gzip64] Put the 'G' mark to encode with Gzip64. This is applicable
402 only to Text/Plain and Application/Postscript since compression
403 is not effective other objects. For example, JPEG is already
405 \\[mew-attach-pgp-sign] Put the 'PS' mark to sign with PGP.
406 \\[mew-attach-pgp-enc] Put the 'PE' mark to encrypt with PGP.
407 Input decryptors' addresses.
408 \\[mew-attach-undo] Unmark. The original mark appears.
411 \\<mew-draft-mode-map>
412 Prepare '~/.mew-fib' like;
414 name: Kazuhiko Yamamoto
417 If you receive a message like;
420 Your e-mail address: |>email<|
422 Type \\<mew-summary-mode-map>\\[mew-summary-reply] in Summary mode to enter Draft mode.
423 Then type \\<mew-draft-mode-map>\\[mew-draft-yank], \\[mew-fib-fill-default], and \\[mew-fib-delete-frame] makes following
426 Your name : Kazuhiko Yamamoto
427 Your e-mail address: Kazu@Mew.org
429 In this way, mew-fil fills up items quoted like |> <| from '~/.mew-fib'.
430 The fill functions described below.
432 \\[mew-fib-fill-default] Fill |>item<| from '~/.mew-fib'.
433 \\[mew-fib-delete-frame] Delete all quotations, i.e. |> <|.
434 \\[mew-fib-next-item] Jump to the next fib item.
435 \\[mew-fib-previous-item] Jump to the previous fib item.
436 \\[mew-fib-flush-input] Flush input from '~/.mew-fib'.
438 Moreover, '~/.mew-fib' supports aliases like;
445 (auto-save-mode mew-draft-mode-auto-save)
446 (make-local-variable 'paragraph-start)
447 (setq paragraph-start (concat "^[ \t]*[-_][-_][-_]+$\\|" paragraph-start))
448 (make-local-variable 'paragraph-separate)
449 (setq paragraph-separate
450 (concat "^[ \t]*[-_][-_][-_]+$\\|" paragraph-separate))
451 (make-local-variable 'mail-header-separator)
452 (setq mail-header-separator mew-header-separator)
453 (setq major-mode 'mew-draft-mode)
454 (use-local-map mew-draft-mode-map)
455 (set-syntax-table mew-draft-mode-syntax-table)
456 (setq mew-cache-message-number (file-name-nondirectory (buffer-file-name)))
457 (cd (expand-file-name mew-home))
458 (if mew-require-final-newline
460 (make-local-variable 'require-final-newline)
461 (setq require-final-newline t)))
464 (set-buffer-menubar current-menubar)
465 (add-submenu nil mew-draft-mode-menu-spec)))
466 (mew-draft-toolbar-update)
467 (make-local-variable 'mew-draft-encrypted-p)
468 (setq mew-draft-encrypted-p encrypted)
469 (make-local-variable 'mew-draft-privacy-error)
470 (setq mew-draft-privacy-error nil)
471 (make-local-variable 'mew-draft-protect-privacy-type)
472 (setq mew-draft-protect-privacy-type nil)
473 (setq mode-line-buffer-identification mew-mode-line-id)
475 (run-hooks 'text-mode-hook 'mew-draft-mode-hook)
476 ;; must be here for auto-fill
477 (if (and auto-fill-function mew-temacs-p)
479 (make-local-variable 'auto-fill-function)
480 (setq auto-fill-function (function mew-draft-auto-fill))))
481 (setq buffer-undo-list nil))
483 (defun draft-mode-name ()
486 (mew-draft-protect-privacy-type
487 (setq sub (nth 2 (assoc mew-draft-protect-privacy-type
488 mew-privacy-database))))
489 ((and mew-draft-encrypted-p mew-protect-privacy-encrypted)
490 (setq sub (nth 2 (assoc mew-protect-privacy-encrypted-type
491 mew-privacy-database))))
492 (mew-protect-privacy-always
493 (setq sub (nth 2 (assoc mew-protect-privacy-always-type
494 mew-privacy-database)))))
496 (setq mode-name (concat "Draft " sub))
497 (setq mode-name "Draft"))
498 (force-mode-line-update)))
500 (defun mew-draft-auto-fill ()
502 (if (mew-in-header-p)
505 (while (not (or (looking-at "[^ \t]+:\\|[ \t]") (bobp)))
508 (beginning-of-line)))))
510 (defun mew-draft-rename (file)
512 (format "^%s\\(.*\\)$" (file-name-as-directory mew-mail-path))
514 (rename-buffer (concat "+" (mew-match 1 file)))))
516 ;; +draft/1 -> +draft/mime/1
517 ;; This function is hard coding due to mew-draft-mime-folder, sigh...
518 (defun mew-draft-to-mime (draft)
519 (concat (file-name-as-directory mew-draft-mime-folder)
520 (file-name-nondirectory draft)))
522 (defun mew-attachdir (&optional draft)
523 (mew-expand-folder (mew-draft-to-mime (or draft (buffer-name)))))
525 (defun mew-draft-header-insert-alist (halist)
526 "Insert field-body: and field-value. Return the value of
528 (let ((case-fold-search t)
531 (setq key (car (car halist)))
532 (setq val (cdr (car halist)))
533 (setq halist (cdr halist))
534 (if (not (string-match ":$" key))
535 (setq key (concat key ":")))
536 (if (string-match mew-body: key)
538 (mew-draft-header-insert key val)))
541 (defun mew-insert-address-list (field adrs del force-insert)
542 (let ((cnt 0) (beg (point)) med adr)
544 (setq adr (car adrs) adrs (cdr adrs))
545 (if (mew-is-my-address del adr)
550 (setq del (cons (concat "^" (regexp-quote adr) "$") del))
551 (setq cnt (1+ cnt))))
552 (if (or force-insert (> cnt 0))
559 (mew-header-fold-region beg (point) med 'use-tab)))
562 (defun mew-insert-address-list2 (field adrs)
565 (let ((beg (point)) med)
569 (setq adrs (cdr adrs))
571 (insert ", " (car adrs))
572 (setq adrs (cdr adrs)))
574 (mew-header-fold-region beg (point) med 'use-tab))))
576 (defun mew-draft-header (&optional subject nl to cc newsgroups in-reply-to references other-headers fromme)
577 ;; to -- string or list
578 ;; cc -- string or list
579 ;; nl -- one empty line under "----", which is necessary if
580 ;; attachment is prepared
581 (let ((del (mew-get-my-address-regex-list)) ;; deleting list for Cc:
583 (goto-char (point-min))
585 ;; All addresses inserted on To: are appended to del.
587 ((null to) (insert mew-to: " \n"))
588 ((stringp to) ;; To: inputed from the mini-buffer.
589 ;; Don't check to is mine. Cc: is also string
590 ;; We believe that user never specifies the same address of To: to Cc:.
591 (insert mew-to: " " to "\n"))
592 ;; To: collected by reply
595 (mew-insert-address-list2 mew-to: to)
596 (setq del (mew-insert-address-list mew-to: to del t)))))
598 ((null cc) ()) ;; do nothing
599 ((stringp cc) ;; Cc: inputed from the mini-buffer.
600 (insert mew-cc: " " cc "\n"))
601 ((listp cc) ;; Cc: collected by reply.
603 (mew-insert-address-list2 mew-cc: cc)
604 (mew-insert-address-list mew-cc: cc del nil))))
605 (mew-draft-header-insert mew-newsgroups: newsgroups)
606 (mew-draft-header-insert mew-cc: mew-cc)
607 (mew-draft-header-insert mew-subj: (or subject ""))
608 (mew-draft-header-insert mew-from: mew-from)
609 (mew-draft-header-insert mew-fcc: mew-fcc)
610 (mew-draft-header-insert mew-dcc: mew-dcc)
611 (mew-draft-header-insert mew-reply-to: mew-reply-to)
612 (mew-draft-header-insert mew-in-reply-to: in-reply-to)
613 (mew-draft-header-insert mew-references: references)
614 (if (and mew-x-face-file
615 (file-exists-p (expand-file-name mew-x-face-file)))
619 (insert-file-contents (expand-file-name mew-x-face-file))
620 (setq xface (mew-buffer-substring (point-min)
621 (max (buffer-size) 1))))
622 (mew-draft-header-insert mew-x-face: xface)))
623 (mew-draft-header-insert mew-x-mailer: mew-x-mailer)
624 (setq body (mew-draft-header-insert-alist other-headers))
625 (mew-draft-header-insert-alist mew-header-alist)
626 (if (and mew-use-config-imget-for-draft
627 (not (string-equal mew-config-imget mew-config-default)))
628 (mew-draft-header-insert mew-config: mew-config-imget))
629 (mew-header-prepared)
631 (if nl (insert "\n"))
632 (if body (save-excursion (insert body)))
633 ;; move the cursor after "To: "
634 (goto-char (point-min))
635 (forward-char 4))) ;; Don't use (end-of-line) since the value may exist.
637 (defun mew-draft-send-letter (&optional preserve)
638 "Send this message. If you skipped 'C-cC-m', the header was
639 modified and you are asked, \"The header was modified.
640 Send this message? \". Type y or n. Mew sends the message
641 in background. So, when you exit Emacs, you may be asked,
642 \"Active processes exist; kill them and exit anyway? (yes or no)\".
643 In this case, check if *mew watch* buffer exists. If so, never
644 exit Emacs because Mew is still sending the message.
645 If executed \\[universal-argument], send this message
646 without killing the draft. This is convenient
647 to send messages to multiple people modifying the draft."
649 (run-hooks 'mew-send-hook)
653 (mew-draft-make-message)
654 (if (or (not mew-ask-send)
655 (y-or-n-p (format "The header was modified. Send this message? ")))
656 (mew-draft-real-send-letter preserve)
660 (mew-draft-real-send-letter preserve)))
662 (defun mew-draft-real-send-letter (&optional preserve)
663 (let ((attachdir (mew-attachdir))
664 (msg (file-name-nondirectory (buffer-file-name)))
665 (process-connection-type mew-connection-type1)
667 (run-hooks 'mew-real-send-hook)
668 (set-buffer-modified-p t) ;; ensure to save
670 mew-cs-dummy mew-cs-mime-trans
672 (setq config (mew-header-get-value mew-config:))
673 (and config (setq config (mew-split config ?,)))
675 (if (not (member (car config) mew-config-list))
677 (setq unknown (concat unknown "," (car config)))
678 (setq unknown (car config))))
679 (setq config (cdr config)))
681 (not (y-or-n-p (format "Unknown Config: selector '%s'. Send this message anyway? " unknown))))
683 (substitute-command-keys
684 "To send this message, edit Config: then type '\\<mew-draft-mode-map>\\[mew-draft-send-letter]'"))
685 ;; learning short names
686 (if (and mew-use-auto-alias mew-addrbook-append-domain-p)
687 ;; If mew-addrbook-append-domain-p is nil, automatic
688 ;; short names would be conflicted to local users.
689 (mapcar (function mew-addrbook-alias-add)
690 (mew-header-parse-address-list (list mew-to: mew-cc:))))
692 (let ((folders (mew-header-get-value mew-fcc:)) folder)
695 (setq folders (mew-addrstr-parse-value-list2 folders))
697 (setq folder (car folders))
698 (if (or (mew-folder-mailp folder)
699 (mew-folder-local-newsp folder)
700 (mew-folder-imapp folder)
701 (file-name-absolute-p folder))
703 (setq folder (concat "+" folder)))
704 (mew-folder-check folder 'force-to-create)
705 (setq folders (cdr folders)))))
709 (setq keep "--preserve=on")
710 (setq keep "--preserve=off")
711 (mew-overlay-delete-buffer)
712 (kill-buffer (current-buffer))
714 (if (mew-current-get 'window)
716 (set-window-configuration (mew-current-get 'window))
717 (mew-current-set 'window nil))))
718 (set-buffer (generate-new-buffer mew-buffer-watch))
720 (setq mew-watch-buffer-process
721 (mew-im-start-process mew-prog-imput
723 "-draftfolder" mew-draft-folder
726 "-watch" "-verbose"))
727 (mew-set-process-cs mew-watch-buffer-process
728 mew-cs-autoconv mew-cs-mime-trans)
729 (set-process-sentinel mew-watch-buffer-process 'mew-watch-sentinel)
730 (message "Sending a message in background")
731 ;; keep +draft/mime/X alive if "C-uC-cC-c".
732 (or preserve (mew-delete-directory-recursively attachdir)))))
734 (defun mew-watch-sentinel (process event)
735 (let ((cbuf (current-buffer)) (kbuf (process-buffer process)))
737 (goto-char (point-min))
738 (if (null (re-search-forward (format "^%s: ERROR:" mew-prog-imput) nil t))
740 (set-buffer cbuf) ;; to avoid cursor-in-echo-area bug
741 (kill-buffer kbuf)) ;; set-buffer before kill-buffer
743 (message "Send failed")
745 (switch-to-buffer (process-buffer process))
746 (local-set-key "\C-c\C-q" 'mew-kill-buffer))))
752 (defun mew-draft-auto-set-input-method ()
753 (if (and (fboundp 'activate-input-method)
754 mew-charset-input-method-alist)
755 (let* ((charset (mew-charset-guess-region
756 (mew-header-end) (or (mew-attach-begin) (point-max))))
757 (method (if (stringp charset)
758 (cdr (mew-assoc-case-equal
759 charset mew-charset-input-method-alist 0)))))
762 (activate-input-method method)
763 (message "Set input method to %s" method))))))
765 (defun mew-draft-yank (&optional arg force)
766 "Copy and paste a part of message from Message mode WITHOUT
767 citation prefix and label.
768 1. Roughly speaking, it copies the body in Message mode. For example,
769 if text/plain is displayed, the entire Message mode is copied.
770 If message/rfc822 is displayed, the body without the header is copied.
771 2. If called with '\\[universal-argument]', the header is also copied if exists.
772 3. If an Emacs mark exists, the target is the region between the mark and
774 ;; MUST take care of C-x C-x
775 ;; MUST be able to cancel by C-x u
777 (if (and (not force) (or (mew-in-header-p) (mew-in-attach-p)))
778 (message "You cannot cite a message here.")
781 (set-buffer (mew-buffer-message))
786 (setq beg (point-min) end (point-max)))
788 (setq beg (region-beginning) end (region-end)))
790 ;; header exists in Message mode
791 (mew-header-goto-body)
792 (setq beg (point) end (point-max)))
794 (setq beg (point-min) end (point-max))))
795 (setq cite (mew-buffer-substring beg end))))
796 (push-mark (point) t t) ;; for C-x C-x
798 (mew-draft-auto-set-input-method))))
800 (defvar mew-message-citation-buffer nil
801 "This value is used by mew-gnus.el to specify a buffer from where
804 (defun mew-draft-cite (&optional arg force)
805 "Copy and paste a part of message from Message mode WITH
806 citation prefix and label.
807 1. Roughly speaking, it copies the body in Message mode. For example,
808 if text/plain is displayed, the entire Message mode is copied.
809 If message/rfc822 is displayed, the body without the header is copied.
810 2. If called with '\\[universal-argument]', the header is also copied if exists.
811 3. If an Emacs mark exists, the target is the region between the mark and
813 ;; MUST take care of C-x C-x
814 ;; MUST be able to cancel by C-x u
816 (if (and (not force) (or (mew-in-header-p) (mew-in-attach-p)))
817 (message "You cannot cite a message here.")
818 (let ((nonmewbuf mew-message-citation-buffer) ;; buffer local, so copy here
819 cite beg end ref-msgid tbuf)
822 ;; extract the body without header
824 (setq tbuf (or nonmewbuf (mew-buffer-message)))
827 (error "No buffer to be cited."))
829 ;; first prepare "cite"
832 ;; arg will be effect in mew-cite-original
834 (setq beg (region-beginning) end (region-end)))
836 ;; header exists in Message mode. Skip the header
837 ;; because we will concatenate it to cite later.
838 (mew-header-goto-body)
839 (setq beg (point) end (point-max)))
841 (setq beg (point-min) end (point-max))))
842 (setq cite (mew-buffer-substring beg end)))
844 ;; see also mew-summary-reply
845 (setq tbuf (or nonmewbuf
847 (set-buffer (mew-buffer-message))
848 (if (mew-header-p) (current-buffer)))
849 ;; header exists only in cache if multipart
850 (mew-cache-hit (mew-current-get 'message))))
853 (error "No buffer to be cited."))
856 (mew-header-goto-end)
857 (setq cite (concat (mew-buffer-substring (point-min) (point))
859 (setq ref-msgid (mew-header-get-value mew-message-id:))))
861 ;; Draft mode, insert the header and the body.
864 ;; append message-id to references
865 (if (and ref-msgid (mew-header-p))
867 (let ((ref (mew-header-get-value mew-references:))
872 (while (string-match "<[^>]+>" rb)
873 (setq refl (cons (mew-match 0 rb) refl))
874 (setq rb (substring rb (match-end 0))))
875 (if (member ref-msgid refl)
876 (setq ref-msgid nil)))
879 (setq ref (concat ref (if ref "\n\t") ref-msgid))
880 (mew-header-delete-lines (list mew-references:))
882 (goto-char (mew-header-end)))
883 (mew-draft-header-insert mew-references: ref)))))
885 ;; this gets complicated due to supercite, please don't care
886 (narrow-to-region (point)(point)) ;; for (goto-char (point-min))
888 (push-mark (point) t t)
889 (goto-char (point-min)))
892 (run-hooks 'mew-cite-hook))
893 (t (mew-cite-original arg)))
894 (mew-draft-auto-set-input-method)
895 (or force (mew-draft-rehighlight)))))
897 (defun mew-cite-original (&optional arg)
898 (if (< (marker-position (mark-marker)) (point))
899 (exchange-point-and-mark))
900 (let ((beg (point)) (end (marker-position (mark-marker)))
903 (narrow-to-region beg end)
905 (setq label (mew-cite-strings))
907 (error "Syntax of mew-cite-format was changed. Read explanation of mew-cite-fields")))
908 (if (null mew-cite-prefix-function)
909 (setq prefix mew-cite-prefix)
910 (setq prefix (funcall mew-cite-prefix-function)))
911 (if mew-cite-prefix-confirmp
912 (let ((ask (read-string
913 (format "Prefix (\"%s\"): " prefix) "")))
914 (if (not (string= ask "")) (setq prefix ask))))
915 ;; C-u C-c C-y cites body with header.
917 ;; header has been already cited. So, delete it.
918 (delete-region beg (progn (mew-header-goto-body) (point))))
920 (push-mark (point) t t) ;; for C-x C-x
921 (and (bolp) (insert prefix))
922 (while (equal 0 (forward-line))
923 (or (equal (point) (point-max))
926 (defun mew-cite-get-value (field)
927 (let ((value (mew-header-get-value field))
929 (if (and (string= mew-from: field) value
930 (setq func (mew-addrbook-func mew-addrbook-for-cite-label)))
932 (setq repl (funcall func (mew-addrstr-parse-address value)))
933 (if repl (setq value repl))))
936 (defun mew-cite-strings ()
937 "A function to create cite label according to
938 'mew-cite-format' and 'mew-cite-fields'."
939 (if (null mew-cite-fields)
941 (apply (function format)
943 (mapcar (function mew-cite-get-value) mew-cite-fields))))
945 (defun mew-cite-prefix-username ()
946 "A good candidate for mew-cite-prefix-function.
947 The citation style is 'from_address> ', e.g. 'kazu> '"
948 (let* ((from (mew-header-parse-address mew-from:))
949 (user (mew-addrstr-extract-user from))
950 (func (mew-addrbook-func mew-addrbook-for-cite-prefix))
952 (if func (setq nickname (funcall func from)))
953 (setq prefix (or nickname user))
954 (if mew-ask-cite-prefix
955 (setq prefix (read-string "Citation prefix: " prefix)))
956 (concat prefix mew-cite-prefix)))
962 (defun mew-draft-kill ()
965 (if (y-or-n-p "Kill draft message? ")
966 (let ((attachdir (mew-attachdir)) ;; attachdir must be here
967 (file (buffer-file-name))
968 (buf (current-buffer)))
969 (mew-overlay-delete-buffer)
972 (if (file-exists-p file) (delete-file file))
973 (if (mew-current-get 'window)
975 (set-window-configuration (mew-current-get 'window))
976 (mew-current-set 'window nil)))
977 (mew-delete-directory-recursively attachdir)
978 (message "Draft was killed"))
979 (message "Draft was not killed")))
981 (defun mew-draft-insert-config (&optional nohighlight)
982 "Insert the Config: header."
984 (let* ((config-cur (mew-header-get-value mew-config:))
985 (config-gus (mew-refile-guess-by-alist1 mew-config-guess-alist))
986 (config-new (if config-gus (mew-join "," config-gus))))
987 (if (and mew-ask-config (not (interactive-p)))
988 (setq config-new (mew-input-config config-new)))
989 (if (and (interactive-p) (not config-new))
990 (setq config-new ""))
993 (or (string= config-cur config-new)
996 (format "Do you want to replace Config value with %s? "
1002 (mew-header-delete-lines (list mew-config:))
1003 (goto-char (mew-header-end))
1004 (mew-draft-header-insert mew-config: config-new)))
1007 (push-mark (point) t t) ;; for C-x C-x
1008 (mew-header-delete-lines (list mew-config:))
1009 (goto-char (mew-header-end))
1010 (mew-draft-header-insert mew-config: config-new)
1013 (mew-draft-rehighlight)))))))
1015 (defun mew-draft-insert-signature ()
1016 "Insert the signature file specified by mew-signature-file.
1017 If attachments exist and mew-signature-as-lastpart is *non-nil*,
1018 the file is attached to the last part. Otherwise, the file is
1019 inserted into the body. If mew-signature-insert-last is *non-nil*,
1020 the file is inserted to the end of the body. Otherwise, inserted
1021 the cursor position."
1023 (let ((sigfile (expand-file-name mew-signature-file)))
1024 (if (not (file-exists-p sigfile))
1025 (message "No signature file %s" sigfile)
1026 (if (and (mew-attach-p) mew-signature-as-lastpart)
1028 (goto-char (point-max))
1030 (mew-attach-forward)
1031 (mew-attach-copy sigfile "Signature")
1032 (mew-attach-disposition "") ;; nil is NG.
1033 (mew-attach-description mew-signature-description))
1034 (if mew-signature-insert-last
1036 (if (null (mew-attach-p))
1037 (goto-char (point-max))
1038 (goto-char (1- (mew-attach-begin))))
1040 (if (null (bolp)) (insert "\n"))))
1041 (insert-file-contents sigfile)))))
1047 (defun mew-save-buffer ()
1048 "Save this buffer with the mew-cs-draft coding-system"
1051 mew-cs-dummy mew-cs-draft
1054 (defun mew-draft-rehighlight ()
1055 "Highlight header and body again."
1057 (mew-highlight-header)
1058 (mew-draft-header-keymap)
1059 (mew-highlight-body))
1065 (defun mew-draft-toggle-privacy-always ()
1066 "Toggle whether or not all drafts are protected."
1068 (setq mew-protect-privacy-always (not mew-protect-privacy-always))
1069 (message "Set mew-protect-privacy-always to %s"
1070 mew-protect-privacy-always)
1073 (defun mew-draft-toggle-privacy-encrypted ()
1074 "Toggle whether or not drafts replying to encrypted messages are
1077 (setq mew-protect-privacy-encrypted (not mew-protect-privacy-encrypted))
1078 (message "Set mew-protect-privacy-encrypted to %s"
1079 mew-protect-privacy-encrypted)
1082 (defun mew-draft-set-privacy-type ()
1083 "\\<mew-draft-mode-map>
1084 Set privacy service which will be effective when \\[mew-draft-make-message]."
1086 (let ((alist (mapcar (function (lambda (x)
1087 (cons (symbol-name (car x))(car x))))
1088 mew-privacy-database))
1091 (setq str (completing-read "Input privacy services : " alist nil t))
1093 (setq mew-draft-protect-privacy-type
1094 (cdr (assoc str alist)))))
1097 (provide 'mew-draft)
1099 ;;; Copyright Notice:
1101 ;; Copyright (C) 1996, 1997, 1998, 1999 Mew developing team.
1102 ;; All rights reserved.
1104 ;; Redistribution and use in source and binary forms, with or without
1105 ;; modification, are permitted provided that the following conditions
1108 ;; 1. Redistributions of source code must retain the above copyright
1109 ;; notice, this list of conditions and the following disclaimer.
1110 ;; 2. Redistributions in binary form must reproduce the above copyright
1111 ;; notice, this list of conditions and the following disclaimer in the
1112 ;; documentation and/or other materials provided with the distribution.
1113 ;; 3. Neither the name of the team nor the names of its contributors
1114 ;; may be used to endorse or promote products derived from this software
1115 ;; without specific prior written permission.
1117 ;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND
1118 ;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1119 ;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1120 ;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE
1121 ;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1122 ;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1123 ;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
1124 ;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
1125 ;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
1126 ;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
1127 ;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1129 ;;; mew-draft.el ends here