;;; emh-comp.el --- emh functions for composing messages ;; Copyright (C) 1993,94,95,96,97,98,99,2000 Free Software Foundation, Inc. ;; Author: MORIOKA Tomohiko ;; OKABE Yasuo ;; Created: 1996/2/29 (separated from tm-mh-e.el) ;; Renamed: 1997/2/21 from tmh-comp.el ;; Keywords: mail composing, MH, MIME, mail ;; This file is part of emh. ;; This program is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as ;; published by the Free Software Foundation; either version 2, or (at ;; your option) any later version. ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;; Code: (require 'mh-comp) (require 'mime-edit) (require 'emh-def) ;; Avoid byte compile warnings. ;; (defvar gnus-article-buffer) ;; (defvar gnus-article-copy) ;; (defvar gnus-original-article-buffer) ;; (eval-when-compile ;; (fset 'gnus-copy-article-buffer 'ignore) ;; ) ;;; @ variable ;;; (defvar emh-forwcomps "forwcomps" "Name of file to be used as a skeleton for forwarding messages. Default is \"forwcomps\". If not a complete path name, the file is searched for first in the user's MH directory, then in the system MH lib directory.") ;; (defvar emh-message-yank-function 'mh-yank-cur-msg) ;;; @ for tm-edit ;;; (defun emh::make-message (folder number) (vector folder number) ) (defun emh::message/folder (message) (elt message 0) ) (defun emh::message/number (message) (elt message 1) ) (defun emh::message/file-name (message) (expand-file-name (emh::message/number message) (mh-expand-file-name (emh::message/folder message)) )) ;;; modified by OKABE Yasuo ;;; 1995/11/14 (cf. [tm-ja:1096]) (defun emh-prompt-for-message (prompt folder &optional default) (let* ((files (directory-files (mh-expand-file-name folder) nil "^[0-9]+$") ) (folder-buf (get-buffer folder)) (default (if folder-buf (save-excursion (set-buffer folder-buf) (let* ((show-buffer (get-buffer mh-show-buffer)) (show-buffer-file-name (buffer-file-name show-buffer))) (if show-buffer-file-name (file-name-nondirectory show-buffer-file-name))))))) (if (or (null default) (not (string-match "^[0-9]+$" default))) (setq default (if (and (string= folder mh-sent-from-folder) mh-sent-from-msg) (int-to-string mh-sent-from-msg) (save-excursion (let (cur-msg) (if (and (= 0 (mh-exec-cmd-quiet nil "pick" folder "cur")) (set-buffer mh-temp-buffer) (setq cur-msg (buffer-string)) (string-match "^[0-9]+$" cur-msg)) (substring cur-msg 0 (match-end 0)) (car files))))))) (completing-read prompt (let ((i 0)) (mapcar (function (lambda (file) (setq i (+ i 1)) (list file i) )) files) ) nil nil default) )) ;;; modified by OKABE Yasuo ;;; 1995/11/14 (cf. [tm-ja:1096]) (defun emh-query-message (&optional message) (let (folder number) (if message (progn (setq folder (emh::message/folder message)) (setq number (emh::message/number message)) )) (or (stringp folder) (setq folder (mh-prompt-for-folder "Message from" (if (and (stringp mh-sent-from-folder) (string-match "^\\+" mh-sent-from-folder)) mh-sent-from-folder "+inbox") nil))) (setq number (if (numberp number) (number-to-string number) (emh-prompt-for-message "Message number: " folder) )) (emh::make-message folder number) )) (defun emh-insert-message (&optional message) ;; always ignores message ;; (let ((article-buffer ;; (if (not (and (stringp mh-sent-from-folder) ;; (numberp mh-sent-from-msg) ;; )) ;; (cond ((and (boundp 'gnus-original-article-buffer) ;; (bufferp mh-sent-from-folder) ;; (get-buffer gnus-original-article-buffer) ;; ) ;; gnus-original-article-buffer) ;; ((and (boundp 'gnus-article-buffer) ;; (get-buffer gnus-article-buffer) ;; (bufferp mh-sent-from-folder) ;; ) ;; (save-excursion ;; (set-buffer gnus-article-buffer) ;; (if (eq major-mode 'mime-view-mode) ;; mime-raw-buffer ;; (current-buffer) ;; ))) ;; )))) (if (null article-buffer) (emh-insert-mail (emh::make-message mh-sent-from-folder mh-sent-from-msg)) ;; (insert-buffer article-buffer) ;; (mime-edit-inserted-message-filter) ;; ) )) (defun emh-insert-mail (&optional message) (save-excursion (save-restriction (let ((message-file (emh::message/file-name (emh-query-message message)))) (narrow-to-region (point) (point)) (insert-file-contents message-file) (push-mark (point-max)) (mime-edit-inserted-message-filter) )))) (set-alist 'mime-edit-message-inserter-alist 'mh-letter-mode (function emh-insert-message)) (set-alist 'mime-edit-mail-inserter-alist 'mh-letter-mode (function emh-insert-mail)) (set-alist 'mime-edit-mail-inserter-alist 'news-reply-mode (function emh-insert-mail)) (set-alist 'mime-edit-split-message-sender-alist 'mh-letter-mode (function (lambda (&optional arg) (interactive "P") (write-region (point-min) (point-max) mime-edit-draft-file-name nil 'no-message) (cond (arg (pop-to-buffer "MH mail delivery") (erase-buffer) (mh-exec-cmd-output mh-send-prog t "-watch" "-nopush" "-nodraftfolder" mh-send-args mime-edit-draft-file-name) (goto-char (point-max)) ; show the interesting part (recenter -1) (sit-for 1)) (t (apply 'mh-exec-cmd-quiet t mh-send-prog (mh-list-to-string (list "-nopush" "-nodraftfolder" "-noverbose" "-nowatch" mh-send-args mime-edit-draft-file-name))))) ))) ;;; @ commands using tm-edit features ;;; (defun emh-edit-again (msg) "Clean-up a draft or a message previously sent and make it resendable. Default is the current message. The variable mh-new-draft-cleaned-headers specifies the headers to remove. See also documentation for `\\[mh-send]' function." (interactive (list (mh-get-msg-num t))) (catch 'tag (let* ((from-folder mh-current-folder) (config (current-window-configuration)) (draft (cond ((and mh-draft-folder (equal from-folder mh-draft-folder)) (let ((name (format "draft-%d" msg))) (if (get-buffer name) (throw 'tag (pop-to-buffer name)) ) (let ((filename (mh-msg-filename msg mh-draft-folder) )) (set-buffer (get-buffer-create name)) (binary-insert-file-contents filename) (setq buffer-file-name filename) ) (pop-to-buffer name) (if (re-search-forward "^-+$" nil t) (replace-match "") ) name)) (t (let ((flag enable-multibyte-characters) (coding-system-for-read 'binary)) (prog1 (mh-read-draft "clean-up" (mh-msg-filename msg) nil) (set-buffer-multibyte flag) )) )))) (goto-char (point-min)) (mh-clean-msg-header (point-min) mh-new-draft-cleaned-headers nil) (let ((cs (detect-coding-region (point-min)(point-max)))) (set-buffer-file-coding-system (if (listp cs) (car cs) cs))) (save-buffer) (mime-edit-again nil 'no-separator 'not-turn-on) (goto-char (point-min)) (mh-compose-and-send-mail draft "" from-folder nil nil nil nil nil nil config) ))) ;;; by OKABE Yasuo ;;; 1996/2/29 (cf. [tm-ja:1643]) (defun emh-extract-rejected-mail (msg) "Extract a letter returned by the mail system and make it re-editable. Default is the current message. The variable mh-new-draft-cleaned-headers gives the headers to clean out of the original message." (interactive (list (mh-get-msg-num t))) (let ((from-folder mh-current-folder) (config (current-window-configuration)) (draft (mh-read-draft "extraction" (mh-msg-filename msg) nil))) (setq buffer-read-only nil) (goto-char (point-min)) (cond ((and (re-search-forward (concat "^\\($\\|[Cc]ontent-[Tt]ype:[ \t]+multipart/\\)") nil t) (not (bolp)) (re-search-forward "boundary=\"\\([^\"]+\\)\"" nil t)) (let ((case-fold-search t) (boundary (buffer-substring (match-beginning 1) (match-end 1)))) (cond ((re-search-forward (concat "^--" boundary "\n" "content-type:[ \t]+" "\\(message/rfc822\\|text/rfc822-headers\\)\n" "\\(.+\n\\)*\n") nil t) (delete-region (point-min) (point)) (mh-clean-msg-header (point-min) mh-new-draft-cleaned-headers nil) (search-forward (concat "\n--" boundary "--\n") nil t) (delete-region (match-beginning 0) (point-max))) (t (message "Seems no message/rfc822 part."))))) ((re-search-forward mh-rejected-letter-start nil t) (skip-chars-forward " \t\n") (delete-region (point-min) (point)) (mh-clean-msg-header (point-min) mh-new-draft-cleaned-headers nil)) (t (message "Does not appear to be a rejected letter."))) (goto-char (point-min)) (if (re-search-forward "^-+$" nil t) (replace-match "") ) (mime-edit-again nil t t) (goto-char (point-min)) (set-buffer-modified-p nil) (mh-compose-and-send-mail draft "" from-folder msg (mh-get-header-field "To:") (mh-get-header-field "From:") (mh-get-header-field "Cc:") nil nil config))) ;;; by OKABE Yasuo ;;; 1995/11/14 (cf. [tm-ja:1099]) (defun emh-forward (to cc &optional msg-or-seq) "Forward a message or message sequence as MIME message/rfc822. Defaults to displayed message. If optional prefix argument provided, then prompt for the message sequence. See also documentation for `\\[mh-send]' function." (interactive (list (mh-read-address "To: ") (mh-read-address "Cc: ") (if current-prefix-arg (mh-read-seq-default "Forward" t) (mh-get-msg-num t) ))) (or msg-or-seq (setq msg-or-seq (mh-get-msg-num t))) (let* ((folder mh-current-folder) (config (current-window-configuration)) ;; uses "draft" for compatibility with forw. ;; forw always leaves file in "draft" since it doesn't have -draft (draft-name (expand-file-name "draft" mh-user-path)) (draft (cond ((or (not (file-exists-p draft-name)) (y-or-n-p "The file `draft' exists. Discard it? ")) (mh-exec-cmd "comp" "-noedit" "-nowhatnowproc" "-form" emh-forwcomps "-nodraftfolder") (prog1 (mh-read-draft "" draft-name t) (mh-insert-fields "To:" to "Cc:" cc) (set-buffer-modified-p nil))) (t (mh-read-draft "" draft-name nil))))) (let ((tag-regexp (concat "^" (regexp-quote (mime-make-tag "message" "rfc822")))) orig-from orig-subject multipart-flag) (goto-char (point-min)) (save-excursion (save-restriction (goto-char (point-max)) (if (not (bolp)) (insert "\n")) (let ((beg (point))) (narrow-to-region beg beg) (mh-exec-cmd-output "pick" nil folder msg-or-seq) (if (> (count-lines (point) (point-max)) 1) (setq multipart-flag t) ) (while (re-search-forward "^\\([0-9]+\\)\n" nil t) (let ((forw-msg (buffer-substring (match-beginning 1) (match-end 1))) (beg (match-beginning 0)) (end (match-end 0)) ) (save-restriction (narrow-to-region beg end) ;; modified for Emacs 18 (delete-region beg end) (insert-file-contents (mh-expand-file-name forw-msg (mh-expand-file-name folder)) ) (save-excursion (push-mark (point-max)) (mime-edit-inserted-message-filter)) (goto-char (point-max)) ) (save-excursion (goto-char beg) (mime-edit-insert-tag "message" "rfc822") ))) (delete-region (point) (point-max)) (if multipart-flag (mime-edit-enclose-digest-region beg (point)) )))) (re-search-forward tag-regexp) (forward-line 1) (save-restriction (narrow-to-region (point) (point-max)) (setq orig-from (eword-decode-string (mh-get-header-field "From:"))) (setq orig-subject (eword-decode-string (mh-get-header-field "Subject:"))) ) (let ((forw-subject (mh-forwarded-letter-subject orig-from orig-subject))) (mh-insert-fields "Subject:" forw-subject) (goto-char (point-min)) (re-search-forward tag-regexp) (forward-line -1) (delete-other-windows) (if (numberp msg-or-seq) (mh-add-msgs-to-seq msg-or-seq 'forwarded t) (mh-add-msgs-to-seq (mh-seq-to-msgs msg-or-seq) 'forwarded t)) (mh-compose-and-send-mail draft "" folder msg-or-seq to forw-subject cc mh-note-forw "Forwarded:" config))))) (cond ((not (featurep 'mh-utils)) (defun emh::insert-letter (folder number verbatim) (mh-insert-letter verbatim folder number) ) ) ((and (boundp 'mh-e-version) (string-lessp mh-e-version "5")) (defun emh::insert-letter (folder number verbatim) (mh-insert-letter number folder verbatim) ) ) (t (defalias 'emh::insert-letter 'mh-insert-letter) )) (defun emh-insert-letter (verbatim) "Interface to mh-insert-letter." (interactive "P") (let* ((folder (mh-prompt-for-folder "Message from" (if (and (stringp mh-sent-from-folder) (string-match "^\\+" mh-sent-from-folder)) mh-sent-from-folder "+inbox") nil)) (number (emh-prompt-for-message "Message number: " folder))) (emh::insert-letter folder number verbatim))) ;; (defun emh-yank-cur-msg-with-no-filter () ;; "Insert the current message into the draft buffer. ;; This function makes new show-buffer from article-buffer to disable ;; variable `mime-preview-text/plain-hook'. If you don't want to use text ;; filters for replying message, please set it to ;; `emh-message-yank-function'. ;; Prefix each non-blank line in the message with the string in ;; `mh-ins-buf-prefix'. The entire message will be inserted if ;; `mh-yank-from-start-of-msg' is non-nil. If this variable is nil, the ;; portion of the message following the point will be yanked. If ;; `mh-delete-yanked-msg-window' is non-nil, any window displaying the ;; yanked message will be deleted." ;; (interactive) ;; (if (and mh-sent-from-folder mh-sent-from-msg) ;; (let ((to-point (point)) ;; (to-buffer (current-buffer))) ;; (set-buffer mh-sent-from-folder) ;; (if mh-delete-yanked-msg-window ;; (delete-windows-on mh-show-buffer)) ;; (set-buffer mh-show-buffer) ; Find displayed message ;; (let ((mh-ins-str ;; (if mime-raw-buffer ;; (let (mime-display-text/plain-hook buf) ;; (prog1 ;; (save-window-excursion ;; (set-buffer mime-raw-buffer) ;; (setq buf (mime-view-mode)) ;; (buffer-string) ;; ) ;; (kill-buffer buf) ;; )) ;; (buffer-string) ;; ))) ;; (set-buffer to-buffer) ;; (save-restriction ;; (narrow-to-region to-point to-point) ;; (push-mark) ;; (insert mh-ins-str) ;; (mh-insert-prefix-string mh-ins-buf-prefix) ;; (insert "\n")))) ;; (error "There is no current message"))) ;; (defun emh-yank-current-message () ;; "Insert the current message into the draft buffer. ;; It uses variable `emh-message-yank-function' ;; to select message yanking function." ;; (interactive) ;; (let ((mh-sent-from-folder mh-sent-from-folder) ;; (mh-sent-from-msg mh-sent-from-msg)) ;; (if (and (not (stringp mh-sent-from-folder)) ;; (boundp 'gnus-article-buffer) ;; (get-buffer gnus-article-buffer) ;; (bufferp mh-sent-from-folder) ;; ) ; might be called from GNUS ;; (if (boundp 'gnus-article-copy) ; might be sgnus ;; (save-excursion ;; (gnus-copy-article-buffer) ;; (setq mh-sent-from-folder gnus-article-copy) ;; (set-buffer mh-sent-from-folder) ;; (setq mh-show-buffer gnus-article-copy) ;; ) ;; (save-excursion ;; (setq mh-sent-from-folder gnus-article-buffer) ;; (set-buffer gnus-article-buffer) ;; (setq mh-show-buffer (current-buffer)) ;; ))) ;; (funcall emh-message-yank-function) ;; )) ;; (substitute-key-definition ;; 'mh-yank-cur-msg 'emh-yank-current-message mh-letter-mode-map) ;; (substitute-key-definition ;; 'mh-insert-letter 'emh-insert-letter mh-letter-mode-map) ;;; @ end ;;; (provide 'emh-comp) (require 'emh) ;;; emh-comp.el ends here