* wl-vars.el (wl-message-use-header-narrowing): New user option.
[elisp/wanderlust.git] / wl / wl-summary.el
index a57ec6d..476b6f7 100644 (file)
@@ -91,7 +91,7 @@
 (defvar wl-summary-buffer-temp-mark-column nil)
 (defvar wl-summary-buffer-persistent-mark-column nil)
 
-(defvar wl-summary-buffer-unsync-mark-number-list nil)
+(defvar wl-summary-buffer-persistent-mark-version 0)
 
 (defvar wl-summary-buffer-persistent nil)
 (defvar wl-summary-buffer-thread-nodes nil)
 (defvar wl-summary-buffer-mode-line nil)
 (defvar wl-summary-buffer-display-mime-mode 'mime)
 (defvar wl-summary-buffer-display-header-mode 'partial)
-(defvar wl-summary-buffer-event-handler nil)
 
 (defvar wl-thread-indent-level-internal nil)
 (defvar wl-thread-have-younger-brother-str-internal nil)
 (make-variable-buffer-local 'wl-summary-buffer-number-column)
 (make-variable-buffer-local 'wl-summary-buffer-temp-mark-column)
 (make-variable-buffer-local 'wl-summary-buffer-persistent-mark-column)
-(make-variable-buffer-local 'wl-summary-buffer-unsync-mark-number-list)
+(make-variable-buffer-local 'wl-summary-buffer-persistent-mark-version)
 (make-variable-buffer-local 'wl-summary-buffer-persistent)
 (make-variable-buffer-local 'wl-summary-buffer-thread-nodes)
 (make-variable-buffer-local 'wl-summary-buffer-prev-refile-destination)
 (make-variable-buffer-local 'wl-summary-buffer-mode-line)
 (make-variable-buffer-local 'wl-summary-buffer-display-mime-mode)
 (make-variable-buffer-local 'wl-summary-buffer-display-header-mode)
-(make-variable-buffer-local 'wl-summary-buffer-event-handler)
 
 (defvar wl-datevec)
 (defvar wl-thr-indent-string)
@@ -612,7 +610,8 @@ See also variable `wl-use-petname'."
        (save-excursion
          (goto-char beg)
          (while (and (< (point) end) (not (eobp)))
-           (when (null (get-text-property (point) 'face))
+           (when (or (null (get-text-property (point) 'face))
+                     (wl-summary-persistent-mark-invalid-p))
              (setq number (wl-summary-message-number))
              (when number
                (setq flags (elmo-message-flags wl-summary-buffer-elmo-folder
@@ -648,27 +647,56 @@ See also variable `wl-use-petname'."
        'nomini frame))))
 
 ;; Handler of event from elmo-folder
-(eval-and-compile
-  (luna-define-class wl-summary-event-handler (elmo-event-handler)
-                    (buffer))
-  (luna-define-internal-accessors 'wl-summary-event-handler))
-
-(luna-define-method elmo-event-handler-flag-changed ((handler
-                                                     wl-summary-event-handler)
-                                                    numbers)
+(defun wl-summary-update-persistent-mark-on-event (buffer numbers)
   (save-excursion
-    (set-buffer (wl-summary-event-handler-buffer-internal handler))
-    (dolist (number numbers)
-      (when (and (wl-summary-message-visible-p number)
-                (wl-summary-jump-to-msg number))
-       (wl-summary-update-persistent-mark number)))))
+    (set-buffer buffer)
+    (if wl-summary-lazy-update-mark
+       (let ((window-list (get-buffer-window-list (current-buffer) 'nomini t))
+             invalidate)
+         (dolist (number numbers)
+           (when (wl-summary-message-visible-p number)
+             (if (catch 'visible
+                   (let ((window-list window-list)
+                         win)
+                     (while (setq win (car window-list))
+                       (when (wl-summary-jump-to-msg number
+                                                     (window-start win)
+                                                     (window-end win))
+                         (throw 'visible t))
+                       (setq window-list (cdr window-list)))))
+                 (wl-summary-update-persistent-mark number)
+               (setq invalidate t))))
+         (when invalidate
+           (wl-summary-invalidate-persistent-mark)
+           (dolist (win window-list)
+             (wl-summary-validate-persistent-mark
+              (window-start win)
+              (window-end win)))))
+      (dolist (number numbers)
+       (when (and (wl-summary-message-visible-p number)
+                  (wl-summary-jump-to-msg number))
+         (wl-summary-update-persistent-mark number))))))
+
+(defun wl-summary-buffer-attach ()
+  (when wl-summary-buffer-elmo-folder
+    (elmo-connect-signal
+     wl-summary-buffer-elmo-folder
+     'flag-changed
+     (current-buffer)
+     (elmo-define-signal-handler (buffer folder numbers)
+       (wl-summary-update-persistent-mark-on-event buffer numbers)))
+    (elmo-connect-signal
+     wl-summary-buffer-elmo-folder
+     'cache-changed
+     (current-buffer)
+     (elmo-define-signal-handler (buffer folder number)
+       (wl-summary-update-persistent-mark-on-event buffer (list number))))))
 
 (defun wl-summary-buffer-detach ()
   (when (and (eq major-mode 'wl-summary-mode)
-            wl-summary-buffer-elmo-folder
-            wl-summary-buffer-event-handler)
-    (elmo-folder-remove-handler wl-summary-buffer-elmo-folder
-                               wl-summary-buffer-event-handler)))
+            wl-summary-buffer-elmo-folder)
+    (elmo-disconnect-signal 'flag-changed (current-buffer))
+    (elmo-disconnect-signal 'cache-changed (current-buffer))))
 
 (defun wl-status-update ()
   (interactive)
@@ -706,21 +734,18 @@ If optional USE-CACHE is non-nil, use cache if exists."
        (folder wl-summary-buffer-elmo-folder))
     (if (null number)
        (message "No message.")
-      (elmo-set-work-buf
-       (elmo-message-fetch folder
-                          number
-                          (elmo-make-fetch-strategy
-                           'entire
-                           use-cache ; use cache
-                           nil ; save cache (should `t'?)
-                           (and
-                            use-cache
-                            (elmo-file-cache-get-path
-                             (elmo-message-field folder number 'message-id))))
-                          nil
-                          (current-buffer)
-                          'unread)
-       (buffer-string)))))
+      (elmo-message-fetch-string folder
+                                number
+                                (elmo-make-fetch-strategy
+                                 'entire
+                                 use-cache ; use cache
+                                 nil ; save cache (should `t'?)
+                                 (and
+                                  use-cache
+                                  (elmo-file-cache-get-path
+                                   (elmo-message-field folder number
+                                                       'message-id))))
+                                'unread))))
 
 (defun wl-summary-reedit (&optional arg)
   "Re-edit current message.
@@ -728,7 +753,7 @@ If ARG is non-nil, Supersedes message"
   (interactive "P")
   (wl-summary-toggle-disp-msg 'off)
   (cond
-   ((not (wl-summary-message-number))
+   ((null (wl-summary-message-number))
     (message "No message."))
    (arg
     (wl-summary-supersedes-message))
@@ -738,7 +763,7 @@ If ARG is non-nil, Supersedes message"
        (mail-position-on-field "Newsgroups")
       (mail-position-on-field "To")))
    (t
-    (wl-draft-edit-string (wl-summary-message-string)))))
+    (wl-draft-edit-string (wl-summary-message-string 'maybe)))))
 
 (defun wl-summary-resend-bounced-mail ()
   "Re-mail the current message.
@@ -854,11 +879,7 @@ you."
   (setq wl-summary-buffer-persistent
        (wl-folder-persistent-p (elmo-folder-name-internal folder)))
   (elmo-folder-set-persistent-internal folder wl-summary-buffer-persistent)
-  (elmo-folder-add-handler folder
-                          (setq wl-summary-buffer-event-handler
-                                (luna-make-entity
-                                 'wl-summary-event-handler
-                                 :buffer (current-buffer))))
+  (wl-summary-buffer-attach)
   ;; process duplicates.
   (elmo-folder-set-process-duplicates-internal
    folder (cdr (elmo-string-matched-assoc
@@ -919,9 +940,9 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
        (add-hook hook function nil t)))
     (add-hook 'window-size-change-functions
              #'wl-summary-after-resize-function))
-  (make-local-hook 'change-major-mode-hook)
-  (add-hook 'change-major-mode-hook #'wl-summary-buffer-detach nil t)
-  (add-hook 'kill-buffer-hook #'wl-summary-buffer-detach)
+  (dolist (hook '(change-major-mode-hook kill-buffer-hook))
+    (make-local-hook hook)
+    (add-hook hook #'wl-summary-buffer-detach nil t))
   ;; This hook may contain the function `wl-setup-summary' for reasons
   ;; of system internal to accord facilities for the Emacs variants.
   (run-hooks 'wl-summary-mode-hook))
@@ -1075,7 +1096,7 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
          wl-thread-entities nil
          wl-summary-scored nil
          wl-summary-buffer-number-list nil
-         wl-summary-buffer-unsync-mark-number-list nil
+         wl-summary-buffer-persistent-mark-version 0
          wl-summary-buffer-target-mark-list nil
          wl-summary-buffer-temp-mark-list nil
          wl-summary-delayed-update nil)
@@ -1548,20 +1569,11 @@ If ARG is non-nil, checking is omitted."
            (save-excursion
              (save-match-data
                ;; online
-               (if (or arg (not file-cached))
-                   (elmo-message-encache
-                    wl-summary-buffer-elmo-folder
-                    number))
+               (when (or arg (not file-cached))
+                 (elmo-message-encache wl-summary-buffer-elmo-folder
+                                       number))
                (elmo-message-set-cached wl-summary-buffer-elmo-folder
-                                        number t)
-               (when (and (wl-summary-jump-to-msg number)
-                          (wl-summary-update-persistent-mark))
-                 (sit-for 0)
-                 (wl-summary-count-unread)
-                 (wl-summary-update-modeline)
-                 (wl-folder-update-unread
-                  (wl-summary-buffer-folder-name)
-                  wl-summary-buffer-unread-count)))
+                                        number t))
              t)
          nil)))))
 
@@ -1741,7 +1753,7 @@ If ARG is non-nil, checking is omitted."
           number)
       (setq number (wl-summary-message-number))
       (elmo-message-set-cached folder number nil)
-      (when (wl-summary-update-persistent-mark)
+      (ignore-errors
        (elmo-file-cache-delete
         (elmo-file-cache-get-path
          (elmo-message-field wl-summary-buffer-elmo-folder
@@ -1761,7 +1773,6 @@ If ARG is non-nil, checking is omitted."
        (setq msgid (elmo-message-field folder number 'message-id))
        (elmo-message-set-cached folder number
                                 (elmo-file-cache-exists-p msgid))
-       (wl-summary-update-persistent-mark)
        (forward-line 1))
       (wl-summary-count-unread)
       (wl-summary-update-modeline)
@@ -1815,12 +1826,7 @@ If ARG is non-nil, checking is omitted."
     (goto-char beg)
     (while (and (< (point) end) (not (eobp)))
       (when (or (not check)
-               (let ((number (wl-summary-message-number)))
-                 (when (memq number wl-summary-buffer-unsync-mark-number-list)
-                   (setq wl-summary-buffer-unsync-mark-number-list
-                         (delq number
-                               wl-summary-buffer-unsync-mark-number-list))
-                   t)))
+               (wl-summary-persistent-mark-invalid-p))
        (wl-summary-update-persistent-mark))
       (forward-line 1))))
 
@@ -2075,18 +2081,27 @@ This function is defined for `window-scroll-functions'"
   (setq wl-summary-buffer-mode-line
        (funcall wl-summary-buffer-mode-line-formatter)))
 
-(defun wl-summary-jump-to-msg (&optional number)
+(defun wl-summary-jump-to-msg (&optional number beg end)
   (interactive "NJump to Number:")
   (let ((num (or number
                 (string-to-int
-                 (read-from-minibuffer "Jump to Message(No.): ")))))
-    (setq num (int-to-string num))
-    (beginning-of-line)
-    (if (or (and (re-search-forward (concat "\r" num "[^0-9]") nil t)
-                (progn (backward-char 1) t))
-           (re-search-backward (concat "\r" num "[^0-9]") nil t))
-       (progn (beginning-of-line) t)
-      nil)))
+                 (read-from-minibuffer "Jump to Message(No.): "))))
+       (pos (point))
+       regexp)
+    (setq regexp (concat "\r" (int-to-string num) "[^0-9]"))
+    (if (and beg end (or (< pos beg) (< end pos)))
+       (progn
+         (goto-char beg)
+         (if (re-search-forward regexp end t)
+             (progn (backward-char 1) (beginning-of-line) t)
+           (goto-char pos)
+           nil))
+      (beginning-of-line)
+      (if (or (and (re-search-forward regexp end t)
+                  (progn (backward-char 1) t))
+             (re-search-backward regexp beg t))
+         (progn (beginning-of-line) t)
+       nil))))
 
 (defun wl-summary-highlight-msgs (msgs)
   (save-excursion
@@ -2162,21 +2177,16 @@ If ARG, without confirm."
 
 (defun wl-summary-load-file-object (filename)
   "Load lisp object from dir."
-  (save-excursion
-    (let ((tmp-buffer (get-buffer-create " *wl-summary-load-file-object*"))
-         insert-file-contents-pre-hook   ; To avoid autoconv-xmas...
+  (with-temp-buffer
+    (let (insert-file-contents-pre-hook        ; To avoid autoconv-xmas...
          insert-file-contents-post-hook
          ret-val)
       (if (not (file-readable-p filename))
          ()
-       (set-buffer tmp-buffer)
        (as-binary-input-file (insert-file-contents filename))
-       (setq ret-val
-             (condition-case nil
-                 (read (current-buffer))
-               (error (error "Reading failed")))))
-      (kill-buffer tmp-buffer)
-      ret-val)))
+       (condition-case nil
+           (read (current-buffer))
+         (error (error "Reading failed")))))))
 
 (defun wl-summary-goto-folder (&optional arg)
   (interactive "P")
@@ -2239,7 +2249,7 @@ If ARG, without confirm."
                   wl-summary-buffer-message-modified
                   wl-summary-buffer-thread-modified
                   wl-summary-buffer-number-list
-                  wl-summary-buffer-unsync-mark-number-list
+                  wl-summary-buffer-persistent-mark-version
                   wl-summary-buffer-folder-name
                   wl-summary-buffer-line-formatter)
                 (and (eq wl-summary-buffer-view 'thread)
@@ -2368,6 +2378,7 @@ If ARG, without confirm."
          (setq wl-summary-buffer-disp-msg nil)
          (setq wl-summary-buffer-last-displayed-msg nil)
          (setq wl-summary-buffer-current-msg nil)
+         (setq wl-summary-buffer-persistent-mark-version 0)
          (let ((inhibit-read-only t)
                (buffer-read-only nil))
            (erase-buffer)
@@ -2405,8 +2416,6 @@ If ARG, without confirm."
            (wl-summary-update-modeline)))
       (unless (eq wl-summary-buffer-view 'thread)
        (wl-summary-make-number-list))
-      (setq wl-summary-buffer-unsync-mark-number-list
-           (copy-sequence wl-summary-buffer-number-list))
       (when (and wl-summary-cache-use
                 (or (and wl-summary-check-line-format
                          (wl-summary-line-format-changed-p))
@@ -2484,7 +2493,8 @@ If ARG, without confirm."
              (wl-message-buffer-prefetch
               folder
               (wl-summary-message-number)
-              wl-message-buffer-prefetch-depth
+              (min (or wl-message-buffer-prefetch-depth 0)
+                   (1- wl-message-buffer-cache-size))
               (current-buffer)
               wl-summary-buffer-mime-charset))
          (if mes (message "%s" mes))
@@ -2800,7 +2810,7 @@ If ARG, without confirm."
                          'in-msgdb)
                         (error "No messages")))
           (condition (car (elmo-parse-search-condition
-                           (elmo-read-search-condition
+                           (wl-read-search-condition
                             wl-summary-pick-field-default))))
           (result (elmo-folder-search wl-summary-buffer-elmo-folder
                                       condition
@@ -2841,7 +2851,7 @@ If ARG, exit virtual folder."
   (if arg
       (wl-summary-unvirtual)
     (wl-summary-goto-folder-subr (concat "/"
-                                        (elmo-read-search-condition
+                                        (wl-read-search-condition
                                          wl-summary-pick-field-default)
                                         "/"
                                         (wl-summary-buffer-folder-name))
@@ -2877,6 +2887,31 @@ If ARG, exit virtual folder."
        (wl-summary-get-score-mark number)
        " ")))
 
+(defun wl-summary-persistent-mark-invalid-p ()
+  (not
+   (equal
+    ;; mey be nil.
+    (get-text-property (point) 'wl-summary-persistent-mark-version)
+    wl-summary-buffer-persistent-mark-version)))
+
+(defun wl-summary-validate-persistent-mark (beg end)
+  (let ((inhibit-read-only t)
+       (buffer-read-only nil))
+    (put-text-property beg end
+                      'wl-summary-persistent-mark-version
+                      wl-summary-buffer-persistent-mark-version)
+    (set-buffer-modified-p nil)))
+
+(defun wl-summary-validate-persistent-mark-string (string)
+  (put-text-property 0 (length string)
+                    'wl-summary-persistent-mark-version
+                    wl-summary-buffer-persistent-mark-version
+                    string))
+
+(defun wl-summary-invalidate-persistent-mark ()
+  (setq wl-summary-buffer-persistent-mark-version
+       (1+ wl-summary-buffer-persistent-mark-version)))
+
 (defsubst wl-summary-persistent-mark-string (folder flags cached)
   "Return the persistent mark string.
 The mark is decided according to the FOLDER, FLAGS and CACHED."
@@ -3058,11 +3093,14 @@ Return non-nil if the mark is updated"
                (buffer-read-only nil)
                (mark (buffer-substring (- (point) 1) (point)))
                (new-mark (wl-summary-persistent-mark number flags)))
-           (unless (string= new-mark mark)
-             (delete-backward-char 1)
-             (insert new-mark)
-             (wl-summary-set-message-modified)
-             t))))
+           (prog1
+               (unless (string= new-mark mark)
+                 (delete-backward-char 1)
+                 (insert new-mark)
+                 (wl-summary-set-message-modified)
+                 t)
+             (wl-summary-validate-persistent-mark (point-at-bol)
+                                                  (point-at-eol))))))
     (when wl-summary-highlight
       (wl-highlight-summary-current-line))
     (set-buffer-modified-p nil)))
@@ -3278,6 +3316,8 @@ Return non-nil if the mark is updated"
       (unless (memq flag elmo-global-flags)
        (when (elmo-local-flag-p flag)
          (error "Cannot treat `%s'." flag))
+       (unless (elmo-flag-valid-p flag)
+         (error "Invalid char in `%s'" flag))
        (if (y-or-n-p (format "Flag `%s' is not registered yet. Register?"
                              (capitalize (symbol-name flag))))
            (setq elmo-global-flags (append
@@ -3494,6 +3534,7 @@ Return non-nil if the mark is updated"
                       (number-to-string
                        (elmo-message-entity-number
                         wl-message-entity))))
+    (wl-summary-validate-persistent-mark-string line)
     (if wl-summary-highlight
        (wl-highlight-summary-line-string
         (elmo-message-entity-number wl-message-entity)
@@ -3620,11 +3661,9 @@ Return non-nil if the mark is updated"
                  (write-region-as-binary (point-min)(point-max)
                                          cache nil 'no-msg)))
              (when (file-writable-p view) ; 'thread or 'sequence
-               (save-excursion
-                 (set-buffer tmp-buffer)
-                 (erase-buffer)
-                 (prin1 save-view tmp-buffer)
-                 (princ "\n" tmp-buffer)
+               (with-temp-buffer
+                 (prin1 save-view (current-buffer))
+                 (princ "\n" (current-buffer))
                  (write-region (point-min) (point-max) view nil 'no-msg))))
          ;; kill tmp buffer.
          (kill-buffer tmp-buffer))))))
@@ -4401,8 +4440,7 @@ Use function list is `wl-summary-write-current-folder-functions'."
             wl-summary-buffer-current-msg
             (wl-summary-message-number)
             (= (wl-summary-message-number) wl-summary-buffer-current-msg))
-    (with-current-buffer wl-message-buffer
-      wl-message-buffer-cur-display-type)))
+    (wl-message-buffer-display-type wl-message-buffer)))
 
 (defun wl-summary-buffer-display-mime-mode ()
   (or (wl-message-display-type-property (wl-summary-message-display-type)
@@ -4436,7 +4474,9 @@ If ARG is numeric number, decode message as following:
        (setq mime-mode (case arg
                          (1 'mime)
                          (2 'header-only)
-                         (3 'as-is))))
+                         (3 'as-is)
+;;;                      (4 'decode-only)
+                         (5 'no-merge))))
        (arg
        ;; Specify coding-system (doesn't change the MIME mode).
        (setq elmo-mime-display-as-is-coding-system
@@ -4486,7 +4526,7 @@ If ARG is numeric number, decode message as following:
         (num (or number (wl-summary-message-number)))
         (wl-mime-charset      wl-summary-buffer-mime-charset)
         (default-mime-charset wl-summary-buffer-mime-charset)
-        no-folder-mark fld-buf fld-win thr-entity
+        fld-buf fld-win thr-entity
         (elmo-message-fetch-confirm (or elmo-message-fetch-confirm
                                         (and force-reload
                                              elmo-message-fetch-threshold))))
@@ -4508,43 +4548,39 @@ If ARG is numeric number, decode message as following:
              (if (setq fld-win (get-buffer-window fld-buf))
                  (delete-window fld-win)))
          (setq wl-current-summary-buffer (current-buffer))
-         (setq no-folder-mark
-               ;; If cache is used, change folder-mark.
-               (if (wl-message-redisplay
-                    folder num
-                    (wl-message-make-display-type
-                     (or mime-mode
-                         (wl-summary-buffer-display-mime-mode))
-                     (or header-mode
-                         (wl-summary-buffer-display-header-mode)))
-                    (or force-reload
-                        (string= (elmo-folder-name-internal folder)
-                                 wl-draft-folder)))
-                   nil
-                 ;; plugged, then leave folder-mark.
-                 (if (and (not (elmo-folder-local-p
-                                wl-summary-buffer-elmo-folder))
-                          (elmo-folder-plugged-p
-                           wl-summary-buffer-elmo-folder))
-                     'leave)))
+         (wl-message-redisplay folder num
+                               (wl-message-make-display-type
+                                (or mime-mode
+                                    (wl-summary-buffer-display-mime-mode))
+                                (or header-mode
+                                    (wl-summary-buffer-display-header-mode)))
+                               (or force-reload
+                                   (string= (elmo-folder-name-internal folder)
+                                            wl-draft-folder)))
          (when (elmo-message-use-cache-p folder num)
            (elmo-message-set-cached folder num t))
          (ignore-errors
            (if (elmo-message-flagged-p wl-summary-buffer-elmo-folder
                                        num
                                        'unread)
-               (wl-summary-mark-as-read num no-folder-mark)
-             (wl-summary-update-persistent-mark)))
+               (wl-summary-mark-as-read num)
+             (wl-summary-count-unread)
+             (wl-summary-update-modeline)
+             (wl-folder-update-unread
+              (wl-summary-buffer-folder-name)
+              wl-summary-buffer-unread-count)))
          (setq wl-summary-buffer-current-msg num)
          (when wl-summary-recenter
            (recenter (/ (- (window-height) 2) 2))
            (if (not wl-summary-indent-length-limit)
                (wl-horizontal-recenter)))
          (wl-highlight-summary-displaying)
-         (wl-message-buffer-prefetch-next folder num
-                                          wl-message-buffer-prefetch-depth
-                                          (current-buffer)
-                                          wl-summary-buffer-mime-charset)
+         (wl-message-buffer-prefetch-next
+          folder num
+          (min (or wl-message-buffer-prefetch-depth 0)
+               (1- wl-message-buffer-cache-size))
+          (current-buffer)
+          wl-summary-buffer-mime-charset)
          (run-hooks 'wl-summary-redisplay-hook))
       (message "No message to display."))))
 
@@ -4649,25 +4685,23 @@ If ARG is numeric number, decode message as following:
   (interactive)
   (let ((filename)
        (num (wl-summary-message-number)))
-    (if (null wl-save-dir)
-       (setq wl-save-dir wl-temporary-file-directory))
+    (unless wl-save-dir
+      (setq wl-save-dir wl-temporary-file-directory))
     (if num
        (save-excursion
          (setq filename (expand-file-name
                          (concat (int-to-string num)
                                  wl-summary-save-file-suffix)
                          wl-save-dir))
-         (if (null (and arg
-                        (null (file-exists-p filename))))
-             (setq filename
-                   (read-file-name "Save to file: " filename)))
-
+         (when (or (null arg)
+                   (file-exists-p filename))
+           (setq filename (read-file-name "Save to file: " filename)))
          (wl-summary-set-message-buffer-or-redisplay)
          (set-buffer (wl-message-get-original-buffer))
-         (if (and (null arg) (file-exists-p filename))
-             (if (y-or-n-p "File already exists.  override it? ")
-                 (write-region (point-min) (point-max) filename))
-           (write-region (point-min) (point-max) filename)))
+         (when (or arg
+                   (not (file-exists-p filename))
+                   (y-or-n-p "File already exists.  override it? "))
+           (write-region-as-binary (point-min) (point-max) filename)))
       (message "No message to save."))
     num))