[comp.emacs] support for draft folder in mh-e

lamy@utegc.UUCP (04/28/87)

The code below allows GNU Emacs version 18 mh-e mode to support multiple draft
messages using the draft folder facility.  mh-read-draft stores a copy of the
completed draft buffer at the appropriate place (in the standard draft file
by default, or in a newly allocated file in the draft folder if the
.mh_profile enables the draft folder facility).  Multiple draft buffers
are supported.  It is also possible (of course) to reuse a draft message or
even a message previously sent.


;; Support for using the MH draft folder facility automatically if defined
;; in .mh_profile. Also adds command to reuse existing message or draft.
;; Modifications by: Jean-Francois Lamy, lamy@ai.toronto.edu (CSNet,UUCP)

(defun mh-read-draft (use initial-contents)
  "Read draft file into a draft buffer.  USE is a message used for prompting
about the intended use of the message.  INITIAL-CONTENTS is filename that
is read into an empty buffer, or NIL if buffer should not be modified.
Returns T if the buffer is set to the contents of this file, NIL otherwise.
If the draft folder facility is enabled in the profile a new buffer is used
each time and saved in the draft folder.  The draft file can then be reused."
  (let ((draft-name (format "%sdraft" mh-user-path)))
    (cond (mh-use-draft-folder
	   (find-file (mh-new-draft-name)))
	  (t
	   (pop-to-buffer "draft")		; Create if necessary
	   (if (buffer-modified-p)
	       (if (y-or-n-p "Draft has been modified; kill anyway? ")
		   (set-buffer-modified-p nil)
		 (error "Draft preserved.")))
	   (setq buffer-file-name draft-name)
	   (clear-visited-file-modtime)
	   (unlock-buffer)))
    (if (file-exists-p draft-name)
	(insert-file-contents draft-name))
    (prog1
	(cond ((and initial-contents
		    (or (zerop (buffer-size))
			(not (y-or-n-p
			      (format "A draft exists.  Use for %s? "
				      use)))))
	       (delete-region (point-min) (point-max))
	       (insert-file-contents initial-contents)
	       t)
	      (t nil))
      (auto-save-mode 1)
      (setq mh-last-draft-buffer (buffer-name))
      (if mh-use-draft-folder ; the draft message was only a scratchpad
	  (progn
	    (save-buffer); so mh-new-draft-name does not reuse this file
	    (if (file-exists-p draft-name)
		(delete-file draft-name)))); scratchpad no more needed
      )))

(defun mh-new-draft-name ()
  "Returns the filename where the standard draft is to be stored,
assuming that the draft folder facility is enabled"
  (save-excursion
    (switch-to-buffer " *mh_temp*")
    (erase-buffer)
    (mh-exec-cmd-output "mhpath" nil mh-draft-folder "new")
    (buffer-substring (point) (1- (mark)))))

(defun mh-find-path ()
  "Set mh-user-path and mh-draft-folder from  ~/.mh_profile."
  (save-window-excursion
    (if (not (file-exists-p "~/.mh_profile"))
	(error "Cannot find .mh_profile file."))
    (switch-to-buffer " *mh_temp*")
    (erase-buffer)
    (insert-file-contents "~/.mh_profile")
    (setq mh-use-draft-folder
	  (not (equal (setq mh-draft-folder
		       (format "+%s" (mh-get-field "Draft-Folder:" )))
		 "+")))
    (if (equal (setq mh-user-path (mh-get-field "Path:")) "")
	(setq mh-user-path "Mail/")
	(setq mh-user-path (format "%s/" mh-user-path)))
    (if (not (equal (substring mh-user-path 0 1) "/"))
	(setq mh-user-path (format "%s/%s" (getenv "HOME") mh-user-path)))))

(defun mh-compose-and-send-mail (send-args sent-from-folder sent-from-msg
					   to subject cc
					   &optional annotate-char
					   annotate-field search-prefix)
  "Edit and compose a draft message and send or save it.
SENT-FROM-FOLDER is buffer containing scan listing of current folder, or
nil if none exists.
SENT-FROM-MSG is the message number or sequence name or nil.
SEND-ARGS is an optional argument passed to the send command.
The TO, SUBJECT, and CC fields are passed to the mh-compose-letter-hook.
If ANNOTATE-CHAR is non-null, it is used to notate the scan listing of the
message.  In that case, the ANNOTATE-FIELD is used to build a string
for mh-annotate-msg."
  (pop-to-buffer mh-last-draft-buffer); ugly, I know
  (mh-letter-mode)
  (make-local-vars
   'mh-send-args send-args
   'mh-sent-from-folder sent-from-folder
   'mh-sent-from-msg sent-from-msg
   'mh-annotate-field annotate-field
   'mh-annotate-char annotate-char
   'mh-annotate-search-prefix (if search-prefix search-prefix ""))
  (setq mode-line-buffer-identification (list "mh-e: {%b}  Mail/draft"))
  (if (and (boundp 'mh-compose-letter-hook) mh-compose-letter-hook)
      (funcall mh-compose-letter-hook to subject cc)))

(defun mh-edit-again (msg)
  "Clean-up a draft or a message previously sent and make it resendable."
  (interactive (list (mh-get-msg-num t)))
  (let ((from-folder mh-current-folder))
    (cond
     ((and mh-use-draft-folder (equal from-folder mh-draft-folder))
      (find-file (format "%s%d" mh-folder-filename msg)))
     (t (mh-read-draft "clean-up" (format "%s%d" mh-folder-filename msg))))
    (mh-clean-msg-header (point-min)
			 "^Date:\\|^Received:\\|^Message-Id:\\|^From:"
			 nil)
    (goto-char (point-min))
    (set-buffer-modified-p nil)
    (mh-compose-and-send-mail "" from-folder nil nil nil nil)
    ))
(define-key mh-folder-mode-map "\ea" 'mh-edit-again)