* wl-draft.el (wl-draft-save):
[elisp/wanderlust.git] / wl / wl-draft.el
index a46d15e..9168336 100644 (file)
 (make-variable-buffer-local 'wl-draft-reply-buffer)
 (make-variable-buffer-local 'wl-draft-parent-folder)
 
-(defsubst wl-smtp-password-key (user mechnism server)
+(defsubst wl-smtp-password-key (user mechanism server)
   (format "SMTP:%s/%s@%s"
-         user mechnism server))
+         user mechanism server))
 
 (defmacro wl-smtp-extension-bind (&rest body)
   (` (let* ((smtp-sasl-mechanisms
@@ -1037,7 +1037,8 @@ non-nil."
          (when session (elmo-network-close-session session)))
       (error
        (elmo-network-close-session session)
-       (signal (car error)(cdr error)))))
+       (unless (string= (nth 1 error) "Unplugged")
+        (signal (car error)(cdr error))))))
   (wl-draft-send-mail-with-smtp))
 
 (defun wl-draft-insert-required-fields (&optional force-msgid)
@@ -1215,14 +1216,39 @@ If KILL-WHEN-DONE is non-nil, current draft buffer is killed"
             (kill-buffer sending-buffer))))))
 
 (defun wl-draft-save ()
-  "Save current draft."
+  "Save current draft.
+Derived from `message-save-drafts' in T-gnus."
   (interactive)
-  (save-buffer)
-  (wl-draft-config-info-operation
-   (and (string-match "[0-9]+$" wl-draft-buffer-file-name)
-       (string-to-int
-        (match-string 0 wl-draft-buffer-file-name)))
-   'save))
+  (if (buffer-modified-p)
+      (progn
+       (message "Saving %s..." wl-draft-buffer-file-name)
+       (let ((msg (buffer-substring-no-properties (point-min) (point-max))))
+         (with-temp-file wl-draft-buffer-file-name
+           (insert msg)
+           ;; If no header separator, insert it.
+           (save-excursion
+             (goto-char (point-min))
+             (unless (re-search-forward
+                      (concat "^" (regexp-quote mail-header-separator) "$")
+                      nil t)
+               (goto-char (point-min))
+               (if (re-search-forward "\n\n" nil t)
+                   (replace-match (concat "\n" mail-header-separator "\n"))
+                 (goto-char (point-max))
+                 (insert (if (eq (char-before) ?\n) "" "\n")
+                         mail-header-separator "\n"))))
+           (let ((mime-header-encode-method-alist
+                  '((eword-encode-unstructured-field-body))))
+             (mime-edit-translate-buffer))
+           (wl-draft-get-header-delimiter t)))
+       (set-buffer-modified-p nil)
+       (wl-draft-config-info-operation
+        (and (string-match "[0-9]+$" wl-draft-buffer-file-name)
+             (string-to-int
+              (match-string 0 wl-draft-buffer-file-name)))
+        'save)
+       (message "Saving %s...done" wl-draft-buffer-file-name))
+    (message "(No changes need to be saved)")))
 
 (defun wl-draft-mimic-kill-buffer ()
   "Kill the current (draft) buffer with query."
@@ -1408,13 +1434,15 @@ If KILL-WHEN-DONE is non-nil, current draft buffer is killed"
           (cons "References: " references)))
     (setq header-alist (append header-alist
                               (wl-draft-default-headers)
-                              (if body (list "\n" body))))
+                              (if body (list "" body))))
     (wl-draft-create-contents header-alist)
     (if edit-again
        (wl-draft-decode-body
         content-type content-transfer-encoding))
     (wl-draft-insert-mail-header-separator)
-    (wl-draft-prepare-edit (interactive-p))
+    (wl-draft-prepare-edit)
+    (if (interactive-p)
+       (run-hooks 'wl-mail-setup-hook))
 
     (goto-char (point-min))
     (wl-user-agent-compose-internal) ;; user-agent
@@ -1507,27 +1535,22 @@ If KILL-WHEN-DONE is non-nil, current draft buffer is killed"
         )))
       (setq halist (cdr halist)))))
 
-(defun wl-draft-prepare-edit (&optional hook)
-  (wl-draft-editor-mode)
-  (wl-draft-overload-functions)
-  (wl-highlight-headers 'for-draft)
-  (if hook (run-hooks 'wl-mail-setup-hook))
-  (as-binary-output-file
-   (write-region (point-min)(point-max) wl-draft-buffer-file-name
-                nil t)))
+(defun wl-draft-prepare-edit ()
+  (unless (eq major-mode 'wl-draft-mode)
+    (error "wl-draft-create-header must be use in wl-draft-mode."))
+  (let (change-major-mode-hook)
+    (wl-draft-editor-mode)
+    (add-hook 'local-write-file-hooks 'wl-draft-save)
+    (wl-draft-overload-functions)
+    (wl-highlight-headers 'for-draft)
+    (wl-draft-save)
+    (clear-visited-file-modtime)))
 
 (defun wl-draft-decode-header ()
   (save-excursion
-    (let (delimline)
-      (goto-char (point-min))
-      (or (search-forward "\n\n" nil t)
-         (goto-char (point-max)))
-      (setq delimline (point))
-      (save-restriction
-       (narrow-to-region (point-min) delimline)
-       (wl-draft-decode-message-in-buffer)
-       (widen))
-    delimline)))
+    (std11-narrow-to-header)
+    (wl-draft-decode-message-in-buffer)
+    (widen)))
 
 (defun wl-draft-decode-body (&optional content-type content-transfer-encoding)
   (let ((content-type
@@ -1537,30 +1560,25 @@ If KILL-WHEN-DONE is non-nil, current draft buffer is killed"
         (or content-transfer-encoding
             (std11-field-body "content-transfer-encoding")))
        delimline)
-    (goto-char (point-min))
-    (if (search-forward "\n\n" nil t)
-       (progn
-         (goto-char (1- (point)))
-         (delete-char 1))
-      (goto-char (point-max)))
-    (setq delimline (point))
     (save-excursion
-      (wl-draft-delete-field "content-type" delimline)
-      (wl-draft-delete-field "content-transfer-encoding" delimline))
-    (when content-type
-      (insert "Content-type: " content-type "\n"))
-    (when content-transfer-encoding
-      (insert "Content-Transfer-Encoding: " content-transfer-encoding "\n"))
-    (if (or content-type content-transfer-encoding)
-       (insert "\n"))
-    (save-restriction
+      (std11-narrow-to-header)
+      (wl-draft-delete-field "content-type")
+      (wl-draft-delete-field "content-transfer-encoding")
+      (goto-char (point-max))
+      (setq delimline (point-marker))
+      (widen)
       (narrow-to-region delimline (point-max))
-      (debug)
+      (goto-char (point-min))
+      (when content-type
+       (insert "Content-type: " content-type "\n"))
+      (when content-transfer-encoding
+       (insert "Content-Transfer-Encoding: " content-transfer-encoding "\n"))
       (wl-draft-decode-message-in-buffer)
-      (widen))
-    (goto-char delimline)
-    (insert "\n")
-    delimline))
+      (goto-char (point-min))
+      (unless (re-search-forward "^$" (point-at-eol) t)
+       (insert "\n"))
+      (widen)
+      delimline)))
 
 ;;; subroutine for wl-draft-create-contents
 ;;; must be used in wl-draft-mode
@@ -1588,8 +1606,7 @@ If KILL-WHEN-DONE is non-nil, current draft buffer is killed"
    (cons "Mail-Reply-To: " (and wl-insert-mail-reply-to
                                (wl-address-header-extract-address
                                 wl-from)))
-   (cons 'insert
-        (list (funcall wl-generate-mailer-string-function) "\n"))
+   (cons "" wl-generate-mailer-string-function)
    (cons "Reply-To: " mail-default-reply-to)
    (cons 'wl-draft-insert-ccs
         (list "Bcc: " (or wl-bcc
@@ -1613,9 +1630,7 @@ If KILL-WHEN-DONE is non-nil, current draft buffer is killed"
        (goto-char delimline)
       (goto-char (point-min))
       (if (search-forward "\n\n" nil t)
-         (progn
-           (goto-char (1- (point)))
-           (delete-char 1))
+         (delete-backward-char 1)
        (goto-char (point-max))))
     (wl-draft-check-new-line)
     (put-text-property (point)
@@ -1668,36 +1683,49 @@ If KILL-WHEN-DONE is non-nil, current draft buffer is killed"
 (defun wl-draft-reedit (number)
   (let ((draft-folder (wl-folder-get-elmo-folder wl-draft-folder))
        (wl-draft-reedit t)
-       buf-name file-name change-major-mode-hook)
+       buffer file-name change-major-mode-hook)
     (setq file-name (elmo-message-file-name draft-folder number))
     (unless (file-exists-p file-name)
       (error "File %s does not exist" file-name))
-    (setq buf-name (find-file-noselect file-name))
-    (if wl-draft-use-frame
-       (switch-to-buffer-other-frame buf-name)
-      (switch-to-buffer buf-name))
-    (set-buffer buf-name)
-    (if (not (string-match (regexp-quote wl-draft-folder)
-                          (buffer-name)))
-       (rename-buffer (concat wl-draft-folder "/" (buffer-name))))
-    (auto-save-mode -1)
-    (wl-draft-mode)
-    (setq wl-sent-message-via nil)
-    (setq wl-sent-message-queued nil)
-    (setq wl-draft-buffer-file-name file-name)
-    (wl-draft-config-info-operation number 'load)
-    (goto-char (point-min))
-    (or (re-search-forward "\n\n" nil t)
-       (search-forward (concat mail-header-separator "\n") nil t))
-    (write-region (point-min)(point-max) wl-draft-buffer-file-name
-                 nil t)
-    (wl-draft-overload-functions)
-    (wl-draft-editor-mode)
-    (wl-highlight-headers 'for-draft)
-    (run-hooks 'wl-draft-reedit-hook)
-    (goto-char (point-max))
-    buf-name
-    ))
+    (if (setq buffer (get-buffer
+                     (concat wl-draft-folder "/"
+                             (number-to-string number))))
+       (progn
+         (if wl-draft-use-frame
+             (switch-to-buffer-other-frame buffer)
+           (switch-to-buffer buffer))
+         (set-buffer buffer))
+      (setq buffer (get-buffer-create (number-to-string number)))
+      (if wl-draft-use-frame
+         (switch-to-buffer-other-frame buffer)
+       (switch-to-buffer buffer))
+      (set-buffer buffer)
+      (insert-file-contents-as-binary file-name)
+      (let((mime-edit-again-ignored-field-regexp
+           "^\\(Content-.*\\|Mime-Version\\):"))
+       (wl-draft-decode-message-in-buffer))
+      (wl-draft-insert-mail-header-separator)
+      (if (not (string-match (regexp-quote wl-draft-folder)
+                            (buffer-name)))
+         (rename-buffer (concat wl-draft-folder "/" (buffer-name))))
+      (auto-save-mode -1)
+      (wl-draft-mode)
+      (setq buffer-file-name file-name)
+      (make-local-variable 'truncate-partial-width-windows)
+      (setq truncate-partial-width-windows nil)
+      (setq truncate-lines wl-draft-truncate-lines)
+      (setq wl-sent-message-via nil)
+      (setq wl-sent-message-queued nil)
+      (setq wl-draft-buffer-file-name file-name)
+      (wl-draft-config-info-operation number 'load)
+      (goto-char (point-min))
+      (wl-draft-overload-functions)
+      (wl-draft-editor-mode)
+      (add-hook 'local-write-file-hooks 'wl-draft-save)
+      (wl-highlight-headers 'for-draft)
+      (run-hooks 'wl-draft-reedit-hook)
+      (goto-char (point-max))
+      buffer)))
 
 (defmacro wl-draft-body-goto-top ()
   (` (progn
@@ -2074,7 +2102,8 @@ If KILL-WHEN-DONE is non-nil, current draft buffer is killed"
          buf draft-bufs)
       (while bufs
        (if (and
-            (setq buf (buffer-file-name (car bufs)))
+            (setq buf (with-current-buffer (car bufs)
+                        wl-draft-buffer-file-name))
             (string-match draft-regexp buf))
            (setq draft-bufs (cons (buffer-name (car bufs)) draft-bufs)))
        (setq bufs (cdr bufs)))