summaryrefslogtreecommitdiff
path: root/lisp/vm.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/vm.el')
-rwxr-xr-xlisp/vm.el1529
1 files changed, 1529 insertions, 0 deletions
diff --git a/lisp/vm.el b/lisp/vm.el
new file mode 100755
index 0000000..9b1395f
--- /dev/null
+++ b/lisp/vm.el
@@ -0,0 +1,1529 @@
+;;; vm.el --- Entry points for VM
+;;
+;; This file is part of VM
+;;
+;; Copyright (C) 1994-1998, 2003 Kyle E. Jones
+;; Copyright (C) 2003-2006 Robert Widhopf-Fenk
+;;
+;; 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 of the License, 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 this program; if not, write to the Free Software Foundation, Inc.,
+;; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+
+;;; History:
+;;
+;; This file was vm-startup.el!
+
+;;; Code:
+
+(provide 'vm)
+
+(require 'vm-version)
+
+(defvar enable-multibyte-characters)
+
+;; For function declarations
+(eval-when-compile
+ (require 'vm-misc)
+ (require 'vm-folder)
+ (require 'vm-summary)
+ (require 'vm-window)
+ (require 'vm-minibuf)
+ (require 'vm-menu)
+ (require 'vm-toolbar)
+ (require 'vm-mouse)
+ (require 'vm-page)
+ (require 'vm-motion)
+ (require 'vm-undo)
+ (require 'vm-delete)
+ (require 'vm-crypto)
+ (require 'vm-mime)
+ (require 'vm-virtual)
+ (require 'vm-pop)
+ (require 'vm-imap)
+ (require 'vm-sort)
+ (require 'vm-reply)
+)
+
+;; vm-xemacs.el is a non-existent file to fool the Emacs 23 compiler
+(declare-function vm-xemacs-set-face-foreground "vm-xemacs.el"
+ (face color &optional locale tag-set how-to-add))
+(declare-function vm-xemacs-set-face-background "vm-xemacs.el"
+ (face color &optional locale tag-set how-to-add))
+(declare-function get-coding-system "vm-xemacs.el" (name))
+(declare-function find-face "vm-xemacs.el" (face-or-name))
+
+(declare-function vm-rfaddons-infect-vm "vm-rfaddons.el"
+ (&optional sit-for option-list exclude-option-list))
+(declare-function vm-summary-faces-mode "vm-summary-faces.el"
+ (&optional arg))
+
+;; Ensure that vm-autoloads is loaded in case the user is using VM 7.x
+;; autoloads
+
+(eval-when (load)
+ (if (not (featurep 'xemacs))
+ (require 'vm-autoloads)))
+
+;;;###autoload
+(defun* vm (&optional folder &key (read-only nil) (access-method nil)
+ (reload nil) (revisit nil))
+ "Read mail under Emacs.
+Optional first arg FOLDER specifies the folder to visit. It can
+be the path name of a local folder or the maildrop specification
+of a POP or IMAP folder. It defaults to the value of
+`vm-primary-inbox'. The folder is visited in a VM buffer is put
+into VM mode, a major mode for reading mail. (See `vm-mode'.)
+
+Prefix arg or optional second arg READ-ONLY non-nil indicates
+that the folder should be considered read only. No attribute
+changes, message additions or deletions will be allowed in the
+visited folder.
+
+Visiting a folder normally causes any contents of its spool files
+to be moved and appended to the folder buffer. You can disable
+this automatic fetching of mail by setting `vm-auto-get-new-mail'
+to nil.
+
+All the messages can be read by repeatedly pressing SPC. Use `n'ext and
+`p'revious to move about in the folder. Messages are marked for
+deletion with `d', and saved to another folder with `s'. Quitting VM
+with `q' saves the buffered folder to disk, but does not expunge
+deleted messages. Use `###' to expunge deleted messages."
+
+ ;; Additional documentation for internal calls to vm:
+
+ ;; *** Note that this function causes the folder buffer to become
+ ;; *** the current-buffer.
+
+ ;; Internally, this function may also be called with a buffer as the
+ ;; FOLDER argument. In that case, the function sets up the buffer
+ ;; as a folder buffer and turns on vm-mode.
+
+ ;; ACCESS-METHOD, if non-nil, indicates that the FOLDER is the
+ ;; maildrop spec of a remote server folder. Possible values for the
+ ;; parameter are 'pop and 'imap. Or, if FOLDER is a buffer instead
+ ;; of a name, it will be set up as a folder buffer using the
+ ;; specified ACCESS-METHOD.
+
+ ;; RELOAD, if non-nil, means that the folder should be reloaded into
+ ;; an existing buffer. All initialisations must be performed but
+ ;; some variables need to be preserved, e.g., vm-folder-access-data.
+
+ ;; REVISIT, if non-nil, means that, if the folder has already been
+ ;; visited, then it should be just selected. No further processing
+ ;; should be done.
+
+ ;; The functions find-name-for-spec and find-spec-for-name translate
+ ;; between folder names and maildrop specs for the server folders.
+
+ (interactive (list nil :read-only current-prefix-arg))
+ (vm-session-initialization)
+ ;; recursive call to vm in order to allow defadvice on its first call
+ (unless (boundp 'vm-session-beginning)
+ (vm folder :read-only read-only :access-method access-method
+ :reload reload :revisit revisit))
+ ;; set inhibit-local-variables non-nil to protect
+ ;; against letter bombs.
+ ;; set enable-local-variables to nil for newer Emacses
+ (catch 'done
+ ;; deduce the access method if none specified
+ (if (null access-method)
+ (let ((f (or folder vm-primary-inbox)))
+ (cond ((bufferp f) ; may be unnecessary. USR, 2010-01
+ (setq access-method vm-folder-access-method))
+ ((and (stringp f)
+ (vm-imap-folder-spec-p f))
+ (setq access-method 'imap
+ folder f))
+ ((and (stringp f)
+ (vm-pop-folder-spec-p f))
+ (setq access-method 'pop
+ folder f)))))
+ (let ((full-startup (and (not reload) (not (bufferp folder))))
+ ;; if we have been asked to visit a folder that is already
+ ;; visited, then we don't do a full-startup unless we are
+ ;; reloading. but what exactly do we do? - USR, 2011-04-24
+ (did-read-index-file nil)
+ folder-buffer first-time totals-blurb
+ folder-name account-name remote-spec
+ preserve-auto-save-file)
+ (cond ((and full-startup (eq access-method 'pop))
+ ;; (setq vm-last-visit-pop-folder folder)
+ (setq remote-spec folder)
+ (setq folder-name (or (vm-pop-find-name-for-spec folder) "POP"))
+ (setq folder (vm-pop-find-cache-file-for-spec remote-spec)))
+ ((and full-startup (eq access-method 'imap))
+ ;; (setq vm-last-visit-imap-folder folder)
+ (setq remote-spec folder)
+ (setq folder-name (or (nth 3 (vm-imap-parse-spec-to-list
+ remote-spec))
+ folder))
+ (if (and vm-imap-refer-to-inbox-by-account-name
+ (equal (downcase folder-name) "inbox")
+ (setq account-name
+ (vm-imap-account-name-for-spec remote-spec)))
+ (setq folder-name account-name))
+ (setq folder (vm-imap-make-filename-for-spec remote-spec))))
+ (setq folder-buffer
+ (if (bufferp folder)
+ folder
+ (vm-read-folder folder remote-spec folder-name)))
+ (set-buffer folder-buffer)
+ ;; Thunderbird folders
+ (let ((msf (concat (buffer-file-name) ".msf")))
+ ;; notice the message summary file of Thunderbird
+ (setq vm-folder-read-thunderbird-status
+ (and (file-exists-p msf)
+ vm-sync-thunderbird-status)))
+ (if (and vm-fsfemacs-mule-p enable-multibyte-characters)
+ (set-buffer-multibyte nil)) ; is this safe?
+ ;; for MULE
+ ;;
+ ;; If the file coding system is not a no-conversion variant,
+ ;; make it so by encoding all the text, then setting the
+ ;; file coding system and decoding it. This situation is
+ ;; only possible if a file is visited and then vm-mode is
+ ;; run on it afterwards.
+ ;;
+ ;; There are separate code blocks for FSF Emacs and XEmacs
+ ;; because the coding systems have different names.
+ (defvar buffer-file-coding-system)
+ (if (and (or vm-xemacs-mule-p vm-xemacs-file-coding-p)
+ (not (eq (get-coding-system buffer-file-coding-system)
+ (get-coding-system 'no-conversion-unix)))
+ (not (eq (get-coding-system buffer-file-coding-system)
+ (get-coding-system 'no-conversion-dos)))
+ (not (eq (get-coding-system buffer-file-coding-system)
+ (get-coding-system 'no-conversion-mac)))
+ (not (eq (get-coding-system buffer-file-coding-system)
+ (get-coding-system 'binary))))
+ (let ((buffer-read-only nil)
+ (omodified (buffer-modified-p)))
+ (unwind-protect
+ (progn
+ (encode-coding-region (point-min) (point-max)
+ buffer-file-coding-system)
+ (set-buffer-file-coding-system 'no-conversion nil)
+ (decode-coding-region (point-min) (point-max)
+ buffer-file-coding-system))
+ (set-buffer-modified-p omodified))))
+ (if (and vm-fsfemacs-mule-p (null buffer-file-coding-system))
+ (set-buffer-file-coding-system 'raw-text nil))
+ (if (and vm-fsfemacs-mule-p
+ (not (eq (coding-system-base buffer-file-coding-system)
+ (coding-system-base 'raw-text-unix)))
+ (not (eq (coding-system-base buffer-file-coding-system)
+ (coding-system-base 'raw-text-mac)))
+ (not (eq (coding-system-base buffer-file-coding-system)
+ (coding-system-base 'raw-text-dos)))
+ (not (eq (coding-system-base buffer-file-coding-system)
+ (coding-system-base 'no-conversion))))
+ (let ((buffer-read-only nil)
+ (omodified (buffer-modified-p)))
+ (unwind-protect
+ (progn
+ (encode-coding-region (point-min) (point-max)
+ buffer-file-coding-system)
+ (set-buffer-file-coding-system 'raw-text nil)
+ (decode-coding-region (point-min) (point-max)
+ buffer-file-coding-system))
+ (set-buffer-modified-p omodified))))
+ (vm-check-for-killed-summary)
+ (vm-check-for-killed-presentation)
+ ;; If the buffer's not modified then we know that there can be no
+ ;; messages in the folder that are not on disk.
+ (unless (buffer-modified-p)
+ (setq vm-messages-not-on-disk 0))
+ (setq first-time (not (eq major-mode 'vm-mode))
+ preserve-auto-save-file (and buffer-file-name
+ (not (buffer-modified-p))
+ (file-newer-than-file-p
+ (make-auto-save-file-name)
+ buffer-file-name)))
+ (setq vm-folder-read-only (or preserve-auto-save-file read-only
+ (default-value 'vm-folder-read-only)
+ (and first-time buffer-read-only)))
+ ;; If this is not a VM mode buffer then some initialization
+ ;; needs to be done
+ (if first-time
+ (progn
+ (buffer-disable-undo (current-buffer))
+ (abbrev-mode 0)
+ (auto-fill-mode 0)
+ ;; If an 8-bit message arrives undeclared the 8-bit
+ ;; characters in it should be displayed using the
+ ;; user's default face charset, rather than as octal
+ ;; escapes.
+ (vm-fsfemacs-nonmule-display-8bit-chars)
+ (vm-mode-internal access-method reload)
+ (if full-startup
+ (cond ((eq access-method 'pop)
+ (vm-set-folder-pop-maildrop-spec remote-spec))
+ ((eq access-method 'imap)
+ (vm-set-folder-imap-maildrop-spec remote-spec)
+ (vm-register-folder-garbage
+ 'vm-kill-folder-imap-session nil)
+ )))
+ ;; If the buffer is modified we don't know if the
+ ;; folder format has been changed to be different
+ ;; from index file, so don't read the index file in
+ ;; that case.
+ (if (not (buffer-modified-p))
+ (setq did-read-index-file (vm-read-index-file-maybe)))))
+
+ ;; builds message list, reads attributes if they weren't
+ ;; read from an index file.
+ ;; but that is not what the code is doing! - USR, 2011-04-24
+ (unless revisit
+ (vm-assimilate-new-messages :read-attributes t
+ :gobble-order (not did-read-index-file)
+ :run-hooks nil))
+
+ (if (and first-time (not did-read-index-file))
+ (progn
+ (vm-gobble-visible-header-variables)
+ (vm-gobble-bookmark)
+ (vm-gobble-pop-retrieved)
+ (vm-gobble-imap-retrieved)
+ (vm-gobble-summary)
+ (vm-gobble-labels)))
+
+ ;; Recall the UID VALIDITY value stored in the cache folder
+ (cond ((eq access-method 'imap)
+ (if vm-imap-retrieved-messages
+ (vm-set-folder-imap-uid-validity
+ (vm-imap-recorded-uid-validity))))
+ ((eq access-method 'pop)
+ ;; FIXME yet to be filled in
+ ))
+
+ (if first-time
+ (vm-start-itimers-if-needed))
+
+ ;; make a new frame if the user wants one. reuse an
+ ;; existing frame that is showing this folder.
+ (if (and full-startup
+ ;; this so that "emacs -f vm" doesn't create a frame.
+ this-command)
+ (apply 'vm-goto-new-folder-frame-maybe
+ (if folder '(folder) '(primary-folder folder))))
+
+ ;; raise frame if requested and apply startup window
+ ;; configuration.
+ (if full-startup
+ (let ((buffer-to-display (or vm-summary-buffer
+ vm-presentation-buffer
+ (current-buffer))))
+ (vm-display buffer-to-display buffer-to-display
+ (list this-command)
+ (list (or this-command 'vm) 'startup))
+ (if vm-raise-frame-at-startup
+ (vm-raise-frame))))
+
+ ;; if the folder is being revisited, nothing more to be done
+ (if (and revisit (not first-time))
+ (throw 'done t))
+
+ ;; say this NOW, before the non-previewers read a message,
+ ;; alter the new message count and confuse themselves.
+ (when full-startup
+ ;; save blurb so we can repeat it later as necessary.
+ (setq totals-blurb (vm-emit-totals-blurb))
+ (if buffer-file-name
+ (vm-store-folder-totals buffer-file-name (cdr vm-totals))))
+
+ (vm-thoughtfully-select-message)
+ (vm-update-summary-and-mode-line)
+ ;; need to do this after any frame creation because the
+ ;; toolbar sets frame-specific height and width specifiers.
+ (vm-toolbar-install-or-uninstall-toolbar)
+
+ (when (and vm-use-menus (vm-menu-support-possible-p))
+ (vm-menu-install-visited-folders-menu))
+
+ (when full-startup
+ (if (and (vm-should-generate-summary)
+ ;; don't generate a summary if recover-file is
+ ;; likely to happen, since recover-file does
+ ;; not work in a summary buffer.
+ (not preserve-auto-save-file))
+ (vm-summarize t nil))
+ ;; raise the summary frame if the user wants frames
+ ;; raised and if there is a summary frame.
+ (if (and vm-summary-buffer
+ vm-mutable-frame-configuration
+ vm-frame-per-summary
+ vm-raise-frame-at-startup)
+ (vm-raise-frame))
+ ;; if vm-mutable-window-configuration is nil, the startup
+ ;; configuration can't be applied, so do
+ ;; something to get a VM buffer on the screen
+ (if vm-mutable-window-configuration
+ (vm-display nil nil (list this-command)
+ (list (or this-command 'vm) 'startup))
+ (save-excursion
+ (switch-to-buffer (or vm-summary-buffer
+ vm-presentation-buffer
+ (current-buffer))))))
+
+ (if vm-message-list
+ ;; don't decode MIME if recover-file is
+ ;; likely to happen, since recover-file does
+ ;; not work in a presentation buffer.
+ (let ((vm-auto-decode-mime-messages
+ (and vm-auto-decode-mime-messages
+ (not preserve-auto-save-file))))
+ (vm-present-current-message)))
+
+ (run-hooks 'vm-visit-folder-hook)
+
+ ;; Warn user about auto save file, if appropriate.
+ (if preserve-auto-save-file
+ (vm-inform 0
+ (substitute-command-keys
+ (concat
+ "Auto save file is newer; consider \\[vm-recover-folder]. "
+ "FOLDER IS READ ONLY."))))
+ ;; if we're not doing a full startup or if doing more would
+ ;; trash the auto save file that we need to preserve,
+ ;; stop here.
+ (if (or (not full-startup) preserve-auto-save-file)
+ (throw 'done t))
+
+ (if (vm-interactive-p)
+ (vm-inform 5 totals-blurb))
+
+ (if (and vm-auto-get-new-mail
+ (not vm-block-new-mail)
+ (not vm-folder-read-only))
+ (progn
+ (vm-inform 6 "Checking for new mail for %s..."
+ (or buffer-file-name (buffer-name)))
+ (if (vm-get-spooled-mail nil) ; automatic is non-interactive!
+ (progn
+ (setq totals-blurb (vm-emit-totals-blurb))
+ (if (vm-thoughtfully-select-message)
+ (vm-present-current-message)
+ (vm-update-summary-and-mode-line))))
+ (vm-inform 5 totals-blurb)))
+
+ ;; Display copyright and copying info.
+ (when (and (vm-interactive-p) (not vm-startup-message-displayed))
+ (vm-display-startup-message)
+ (if (not (input-pending-p))
+ (vm-inform 5 totals-blurb))))))
+
+;;;###autoload
+(defun vm-other-frame (&optional folder read-only)
+ "Like vm, but run in a newly created frame."
+ (interactive (list nil current-prefix-arg))
+ (vm-session-initialization)
+ (if (vm-multiple-frames-possible-p)
+ (if folder
+ (vm-goto-new-frame 'folder)
+ (vm-goto-new-frame 'primary-folder 'folder)))
+ (let ((vm-frame-per-folder nil)
+ (vm-search-other-frames nil))
+ (vm folder :read-only read-only))
+ (if (vm-multiple-frames-possible-p)
+ (vm-set-hooks-for-frame-deletion)))
+
+;;;###autoload
+(defun vm-other-window (&optional folder read-only)
+ "Like vm, but run in a different window."
+ (interactive (list nil current-prefix-arg))
+ (vm-session-initialization)
+ (if (one-window-p t)
+ (split-window))
+ (other-window 1)
+ (let ((vm-frame-per-folder nil)
+ (vm-search-other-frames nil))
+ (vm folder :read-only read-only)))
+
+(put 'vm-mode 'mode-class 'special)
+
+;;;###autoload
+(defun vm-mode (&optional read-only)
+ "Major mode for reading mail.
+
+This is VM.
+
+Use M-x vm-submit-bug-report to submit a bug report.
+
+Commands:
+\\{vm-mode-map}
+
+Customize VM by setting variables and store them in the `vm-init-file'."
+ (interactive "P")
+ (vm (current-buffer) :read-only read-only)
+ (vm-display nil nil '(vm-mode) '(vm-mode)))
+
+;;;###autoload
+(defun vm-visit-folder (folder &optional read-only revisit)
+ "Visit a mail file.
+VM will parse and present its messages to you in the usual way.
+
+First arg FOLDER specifies the mail file to visit. When this
+command is called interactively the file name is read from the
+minibuffer.
+
+Prefix arg or optional second arg READ-ONLY non-nil indicates
+that the folder should be considered read only. No attribute
+changes, messages additions or deletions will be allowed in the
+visited folder.
+
+The optional third arg REVISIT (not available interactively) says
+that, if the folder is already visited, then it should be merely
+selected without doing further processing (such as moving the
+message-pointer or getting new mail)."
+ (interactive
+ (save-current-buffer
+ (vm-session-initialization)
+ (vm-check-for-killed-folder)
+ (vm-select-folder-buffer-if-possible)
+ (let ((default-directory (if vm-folder-directory
+ (expand-file-name vm-folder-directory)
+ default-directory))
+ (default (or vm-last-visit-folder vm-last-save-folder))
+ (this-command this-command)
+ (last-command last-command))
+ (list (vm-read-file-name
+ (format "Visit%s folder:%s "
+ (if current-prefix-arg " read only" "")
+ (if default
+ (format " (default %s)" default)
+ ""))
+ default-directory default nil nil 'vm-folder-history)
+ current-prefix-arg))))
+ (vm-session-initialization)
+ (vm-check-for-killed-folder)
+ (vm-select-folder-buffer-if-possible)
+ (vm-check-for-killed-summary)
+ (setq vm-last-visit-folder folder)
+ (let ((access-method nil) foo)
+ (cond ((and (vm-pop-folder-spec-p folder)
+ (setq foo (vm-pop-find-name-for-spec folder)))
+ (setq folder foo
+ access-method 'pop
+ vm-last-visit-pop-folder folder))
+ ((and (vm-imap-folder-spec-p folder)
+ ;;(setq foo (vm-imap-find-name-for-spec folder))
+ )
+ (setq ;; folder foo
+ access-method 'imap
+ vm-last-visit-imap-folder folder))
+ (t
+ (let ((default-directory
+ (or vm-folder-directory default-directory)))
+ (setq folder (expand-file-name folder)
+ vm-last-visit-folder folder))))
+ (vm folder
+ :read-only read-only :access-method access-method :revisit revisit)))
+
+;;;###autoload
+(defun vm-visit-folder-other-frame (folder &optional read-only)
+ "Like vm-visit-folder, but run in a newly created frame."
+ (interactive
+ (save-current-buffer
+ (vm-session-initialization)
+ (vm-check-for-killed-folder)
+ (vm-select-folder-buffer-if-possible)
+ (let ((default-directory (if vm-folder-directory
+ (expand-file-name vm-folder-directory)
+ default-directory))
+ (default (or vm-last-visit-folder vm-last-save-folder))
+ (this-command this-command)
+ (last-command last-command))
+ (list (vm-read-file-name
+ (format "Visit%s folder in other frame:%s "
+ (if current-prefix-arg " read only" "")
+ (if default
+ (format " (default %s)" default)
+ ""))
+ default-directory default nil nil 'vm-folder-history)
+ current-prefix-arg))))
+ (vm-session-initialization)
+ (if (vm-multiple-frames-possible-p)
+ (vm-goto-new-frame 'folder))
+ (let ((vm-frame-per-folder nil)
+ (vm-search-other-frames nil))
+ (vm-visit-folder folder read-only))
+ (if (vm-multiple-frames-possible-p)
+ (vm-set-hooks-for-frame-deletion)))
+
+;;;###autoload
+(defun vm-visit-folder-other-window (folder &optional read-only)
+ "Like vm-visit-folder, but run in a different window."
+ (interactive
+ (save-current-buffer
+ (vm-session-initialization)
+ (vm-check-for-killed-folder)
+ (vm-select-folder-buffer-if-possible)
+ (let ((default-directory (if vm-folder-directory
+ (expand-file-name vm-folder-directory)
+ default-directory))
+ (default (or vm-last-visit-folder vm-last-save-folder))
+ (this-command this-command)
+ (last-command last-command))
+ (list (vm-read-file-name
+ (format "Visit%s folder in other window:%s "
+ (if current-prefix-arg " read only" "")
+ (if default
+ (format " (default %s)" default)
+ ""))
+ default-directory default nil nil 'vm-folder-history)
+ current-prefix-arg))))
+ (vm-session-initialization)
+ (if (one-window-p t)
+ (split-window))
+ (other-window 1)
+ (let ((vm-frame-per-folder nil)
+ (vm-search-other-frames nil))
+ (vm-visit-folder folder read-only)))
+
+;;;###autoload
+(defun vm-visit-thunderbird-folder (folder &optional read-only)
+ "Visit a mail file maintained by Thunderbird.
+VM will parse and present its messages to you in the usual way.
+
+First arg FOLDER specifies the mail file to visit. When this
+command is called interactively the file name is read from the
+minibuffer.
+
+Prefix arg or optional second arg READ-ONLY non-nil indicates
+that the folder should be considered read only. No attribute
+changes, messages additions or deletions will be allowed in the
+visited folder.
+
+This function differs from `vm-visit-folder' in that it remembers that
+the folder is a foreign folder maintained by Thunderbird. Saving
+of messages is carried out preferentially to other Thunderbird folders."
+ (interactive
+ (save-current-buffer
+ (vm-session-initialization)
+ (vm-check-for-killed-folder)
+ (vm-select-folder-buffer-if-possible)
+ (let ((default-directory
+ (if vm-thunderbird-folder-directory
+ (expand-file-name vm-thunderbird-folder-directory)
+ default-directory))
+ (default (or vm-last-visit-folder vm-last-save-folder))
+ (this-command this-command)
+ (last-command last-command))
+ (list (vm-read-file-name
+ (format "Visit%s folder:%s "
+ (if current-prefix-arg " read only" "")
+ (if default
+ (format " (default %s)" default)
+ ""))
+ default-directory default nil nil 'vm-folder-history)
+ current-prefix-arg))))
+ (vm-session-initialization)
+ (vm-check-for-killed-folder)
+ (vm-select-folder-buffer-if-possible)
+ (vm-check-for-killed-summary)
+ (setq vm-last-visit-folder folder)
+ (let ((default-directory
+ (or vm-thunderbird-folder-directory default-directory)))
+ (setq folder (expand-file-name folder)
+ vm-last-visit-folder folder))
+ (vm folder :read-only read-only)
+ (set (make-local-variable 'vm-foreign-folder-directory)
+ vm-thunderbird-folder-directory)
+ )
+
+;;;###autoload
+(defun vm-visit-pop-folder (folder &optional read-only)
+ "Visit a POP mailbox.
+VM will present its messages to you in the usual way. Messages
+found in the POP mailbox will be downloaded and stored in a local
+cache. If you expunge messages from the cache, the corresponding
+messages will be expunged from the POP mailbox.
+
+First arg FOLDER specifies the name of the POP mailbox to visit.
+You can only visit mailboxes that are specified in `vm-pop-folder-alist'.
+When this command is called interactively the mailbox name is read from the
+minibuffer.
+
+Prefix arg or optional second arg READ-ONLY non-nil indicates
+that the folder should be considered read only. No attribute
+changes, messages additions or deletions will be allowed in the
+visited folder."
+ (interactive
+ (save-current-buffer
+ (vm-session-initialization)
+ (vm-check-for-killed-folder)
+ (vm-select-folder-buffer-if-possible)
+ (require 'vm-pop)
+ (let ((completion-list (mapcar (function (lambda (x) (nth 1 x)))
+ vm-pop-folder-alist))
+ (default vm-last-visit-pop-folder)
+ (this-command this-command)
+ (last-command last-command))
+ (list (vm-read-string
+ (format "Visit%s POP folder:%s "
+ (if current-prefix-arg " read only" "")
+ (if default
+ (format " (default %s)" default)
+ ""))
+ completion-list)
+ current-prefix-arg))))
+ (let (remote-spec)
+ (vm-session-initialization)
+ (vm-check-for-killed-folder)
+ (vm-select-folder-buffer-if-possible)
+ (vm-check-for-killed-summary)
+ (if (and (equal folder "") (stringp vm-last-visit-pop-folder))
+ (setq folder vm-last-visit-pop-folder))
+ (setq vm-last-visit-pop-folder folder)
+ (setq remote-spec (vm-pop-find-spec-for-name folder))
+ (if (null remote-spec)
+ (error "No such POP folder: %s" folder))
+ (vm remote-spec :read-only read-only :access-method 'pop)))
+
+;;;###autoload
+(defun vm-visit-pop-folder-other-frame (folder &optional read-only)
+ "Like vm-visit-pop-folder, but run in a newly created frame."
+ (interactive
+ (save-current-buffer
+ (vm-session-initialization)
+ (vm-check-for-killed-folder)
+ (vm-select-folder-buffer-if-possible)
+ (require 'vm-pop)
+ (let ((completion-list (mapcar (function (lambda (x) (nth 1 x)))
+ vm-pop-folder-alist))
+ (default vm-last-visit-pop-folder)
+ (this-command this-command)
+ (last-command last-command))
+ (list (vm-read-string
+ (format "Visit%s POP folder:%s "
+ (if current-prefix-arg " read only" "")
+ (if default
+ (format " (default %s)" default)
+ ""))
+ completion-list)
+ current-prefix-arg))))
+ (vm-session-initialization)
+ (if (vm-multiple-frames-possible-p)
+ (vm-goto-new-frame 'folder))
+ (let ((vm-frame-per-folder nil)
+ (vm-search-other-frames nil))
+ (vm-visit-pop-folder folder read-only))
+ (if (vm-multiple-frames-possible-p)
+ (vm-set-hooks-for-frame-deletion)))
+
+;;;###autoload
+(defun vm-visit-pop-folder-other-window (folder &optional read-only)
+ "Like vm-visit-pop-folder, but run in a different window."
+ (interactive
+ (save-current-buffer
+ (vm-session-initialization)
+ (vm-check-for-killed-folder)
+ (vm-select-folder-buffer-if-possible)
+ (require 'vm-pop)
+ (let ((completion-list (mapcar (function (lambda (x) (nth 1 x)))
+ vm-pop-folder-alist))
+ (default vm-last-visit-pop-folder)
+ (this-command this-command)
+ (last-command last-command))
+ (list (vm-read-string
+ (format "Visit%s POP folder:%s "
+ (if current-prefix-arg " read only" "")
+ (if default
+ (format " (default %s)" default)
+ ""))
+ completion-list)
+ current-prefix-arg))))
+ (vm-session-initialization)
+ (if (one-window-p t)
+ (split-window))
+ (other-window 1)
+ (let ((vm-frame-per-folder nil)
+ (vm-search-other-frames nil))
+ (vm-visit-pop-folder folder read-only)))
+
+;;;###autoload
+(defun vm-visit-imap-folder (folder &optional read-only)
+ "Visit a IMAP mailbox.
+VM will present its messages to you in the usual way. Messages
+found in the IMAP mailbox will be downloaded and stored in a local
+cache. If you expunge messages from the cache, the corresponding
+messages will be expunged from the IMAP mailbox when the folder is
+saved.
+
+When this command is called interactively, the FOLDER name will
+be read from the minibuffer in the format
+\"account-name:folder-name\", where account-name is the short
+name of an IMAP account listed in `vm-imap-account-alist' and
+folder-name is a folder in this account.
+
+Prefix arg or optional second arg READ-ONLY non-nil indicates
+that the folder should be considered read only. No attribute
+changes, messages additions or deletions will be allowed in the
+visited folder."
+ (interactive
+ (save-current-buffer
+ (vm-session-initialization)
+ (vm-check-for-killed-folder)
+ (vm-select-folder-buffer-if-possible)
+ (require 'vm-imap)
+ (let ((this-command this-command)
+ (last-command last-command))
+ (if (null vm-imap-account-alist)
+ (setq vm-imap-account-alist
+ (mapcar
+ 'reverse
+ (with-no-warnings
+ (vm-imap-spec-list-to-host-alist vm-imap-server-list)))))
+ (list (vm-read-imap-folder-name
+ (format "Visit%s IMAP folder: "
+ (if current-prefix-arg " read only" ""))
+ t nil vm-last-visit-imap-folder)
+ current-prefix-arg))))
+ (vm-session-initialization)
+ (vm-check-for-killed-folder)
+ (vm-select-folder-buffer-if-possible)
+ (setq vm-last-visit-imap-folder folder)
+ (vm folder :read-only read-only :access-method 'imap))
+
+;;;###autoload
+(defun vm-visit-imap-folder-other-frame (folder &optional read-only)
+ "Like vm-visit-imap-folder, but run in a newly created frame."
+ (interactive
+ (save-current-buffer
+ (vm-session-initialization)
+ (vm-check-for-killed-folder)
+ (vm-select-folder-buffer-if-possible)
+ (require 'vm-imap)
+ (let ((this-command this-command)
+ (last-command last-command))
+ (list (vm-read-imap-folder-name
+ (format "Visit%s IMAP folder: "
+ (if current-prefix-arg " read only" ""))
+ nil nil vm-last-visit-imap-folder)
+ current-prefix-arg))))
+ (vm-session-initialization)
+ (if (vm-multiple-frames-possible-p)
+ (vm-goto-new-frame 'folder))
+ (let ((vm-frame-per-folder nil)
+ (vm-search-other-frames nil))
+ (vm-visit-imap-folder folder read-only))
+ (if (vm-multiple-frames-possible-p)
+ (vm-set-hooks-for-frame-deletion)))
+
+;;;###autoload
+(defun vm-visit-imap-folder-other-window (folder &optional read-only)
+ "Like vm-visit-imap-folder, but run in a different window."
+ (interactive
+ (save-current-buffer
+ (vm-session-initialization)
+ (vm-check-for-killed-folder)
+ (vm-select-folder-buffer-if-possible)
+ (require 'vm-imap)
+ (let ((this-command this-command)
+ (last-command last-command))
+ (list (vm-read-imap-folder-name
+ (format "Visit%s IMAP folder: "
+ (if current-prefix-arg " read only" ""))
+ nil nil vm-last-visit-imap-folder)
+ current-prefix-arg))))
+ (vm-session-initialization)
+ (if (one-window-p t)
+ (split-window))
+ (other-window 1)
+ (let ((vm-frame-per-folder nil)
+ (vm-search-other-frames nil))
+ (vm-visit-imap-folder folder read-only)))
+
+
+;;;###autoload
+(defun vm-folder-buffers (&optional non-virtual)
+ "Return the list of buffer names that are currently visiting VM
+folders. The optional argument NON-VIRTUAL says that only
+non-virtual folders should be returned."
+ (save-excursion
+ (let ((buffers (buffer-list))
+ (modes (if non-virtual '(vm-mode) '(vm-mode vm-virtual-mode)))
+ folders)
+ (while buffers
+ (set-buffer (car buffers))
+ (if (member major-mode modes)
+ (setq folders (cons (buffer-name) folders)))
+ (setq buffers (cdr buffers)))
+ folders)))
+(defalias 'vm-folder-list 'vm-folder-buffers)
+
+;; The following function is from vm-rfaddons.el. USR, 2011-02-28
+;;;###autoload
+(defun vm-switch-to-folder (folder-name)
+ "Switch to another opened VM folder and rearrange windows as with a scroll."
+ (interactive (list
+ (let* ((buffers (vm-folder-buffers))
+ (history vm-switch-to-folder-history)
+ pos default)
+ (if (member major-mode
+ '(vm-mode vm-presentation-mode
+ vm-summary-mode))
+ (save-excursion
+ (vm-select-folder-buffer)
+ (setq buffers (delete (buffer-name) buffers))))
+ (setq pos (vm-find history
+ (lambda (f) (member f buffers))))
+ (if pos (setq default (nth pos history)))
+ (completing-read
+ (format "Foldername%s: "
+ (if default (format " (%s)" default) ""))
+ (mapcar (lambda (b) (list b)) (vm-folder-buffers))
+ nil t nil
+ 'vm-switch-to-folder-history
+ default))))
+
+ (switch-to-buffer folder-name)
+ (vm-select-folder-buffer-and-validate 0 (vm-interactive-p))
+ (vm-summarize)
+ (let ((this-command 'vm-scroll-backward))
+ (vm-display nil nil '(vm-scroll-forward vm-scroll-backward)
+ (list this-command 'reading-message))
+ (vm-update-summary-and-mode-line)))
+
+;;;###autoload
+(defun vm-get-folder-buffer (folder)
+ "Returns the buffer visiting FOLDER if it exists, nil otherwise."
+ (let ((buffers (vm-folder-buffers))
+ pos)
+ (setq pos
+ (vm-find buffers
+ (lambda (b)
+ (with-current-buffer b
+ (equal folder (vm-folder-name))))))
+ (and pos (get-buffer (nth pos buffers)))))
+
+
+(put 'vm-virtual-mode 'mode-class 'special)
+
+(defun vm-virtual-mode (&rest ignored)
+ "Mode for reading multiple mail folders as one folder.
+
+The commands available are the same commands that are found in
+vm-mode, except that a few of them are not applicable to virtual
+folders.
+
+vm-virtual-mode is not a normal major mode. If you run it, it
+will not do anything. The entry point to vm-virtual-mode is
+vm-visit-virtual-folder.")
+
+(defvar scroll-in-place)
+
+;;;###autoload
+(defun vm-visit-virtual-folder (folder-name &optional read-only bookmark)
+ (interactive
+ (let ((last-command last-command)
+ (this-command this-command))
+ (vm-session-initialization)
+ (list
+ (vm-read-string (format "Visit%s virtual folder: "
+ (if current-prefix-arg " read only" ""))
+ vm-virtual-folder-alist)
+ current-prefix-arg)))
+ (vm-session-initialization)
+ (require 'vm-virtual)
+ (unless (assoc folder-name vm-virtual-folder-alist)
+ (error "No such virtual folder, %s" folder-name))
+ (let ((buffer-name (concat "(" folder-name ")"))
+ first-time blurb)
+ (set-buffer (get-buffer-create buffer-name))
+ (setq first-time (not (eq major-mode 'vm-virtual-mode)))
+ (when first-time
+ (if (fboundp 'buffer-disable-undo)
+ (buffer-disable-undo (current-buffer))
+ ;; obfuscation to make the v19 compiler not whine
+ ;; about obsolete functions.
+ (let ((x 'buffer-flush-undo))
+ (funcall x (current-buffer))))
+ (abbrev-mode 0)
+ (auto-fill-mode 0)
+ (vm-fsfemacs-nonmule-display-8bit-chars)
+ (setq mode-name "VM Virtual"
+ mode-line-format vm-mode-line-format
+ buffer-read-only t
+ vm-folder-read-only read-only
+ vm-label-obarray (make-vector 29 0)
+ vm-virtual-folder-definition
+ (assoc folder-name vm-virtual-folder-alist))
+ ;; scroll in place messes with scroll-up and this loses
+ (make-local-variable 'scroll-in-place)
+ (setq scroll-in-place nil)
+ (vm-build-virtual-message-list nil)
+ (use-local-map vm-mode-map)
+ (when (vm-menu-support-possible-p)
+ (vm-menu-install-menus))
+ (add-hook 'kill-buffer-hook 'vm-garbage-collect-folder)
+ (add-hook 'kill-buffer-hook 'vm-garbage-collect-message)
+ ;; save this for last in case the user interrupts.
+ ;; an interrupt anywhere before this point will cause
+ ;; everything to be redone next revisit.
+ (setq major-mode 'vm-virtual-mode)
+ (run-hooks 'vm-virtual-mode-hook)
+ ;; must come after the setting of major-mode
+ (setq mode-popup-menu (and vm-use-menus
+ (vm-menu-support-possible-p)
+ (vm-menu-mode-menu)))
+ (setq blurb (vm-emit-totals-blurb))
+ (when vm-summary-show-threads
+ (vm-sort-messages "activity"))
+ (if bookmark
+ (let ((mp vm-message-list))
+ (while mp
+ (if (eq bookmark (vm-real-message-of (car mp)))
+ (progn
+ (vm-record-and-change-message-pointer
+ vm-message-pointer mp)
+ (vm-present-current-message)
+ (setq mp nil))
+ (setq mp (cdr mp))))))
+ (unless vm-message-pointer
+ (if (vm-thoughtfully-select-message)
+ (vm-present-current-message)
+ (vm-update-summary-and-mode-line)))
+ (vm-inform 5 blurb))
+ ;; make a new frame if the user wants one. reuse an
+ ;; existing frame that is showing this folder.
+ (vm-goto-new-folder-frame-maybe 'folder)
+ (if vm-raise-frame-at-startup
+ (vm-raise-frame))
+ (vm-display nil nil (list this-command) (list this-command 'startup))
+ (vm-toolbar-install-or-uninstall-toolbar)
+ (when first-time
+ (when (vm-should-generate-summary)
+ (vm-summarize t nil)
+ (vm-inform 5 blurb))
+ ;; raise the summary frame if the user wants frames
+ ;; raised and if there is a summary frame.
+ (when (and vm-summary-buffer
+ vm-mutable-frame-configuration
+ vm-frame-per-summary
+ vm-raise-frame-at-startup)
+ (vm-raise-frame))
+ ;; if vm-mutable-window-configuration is nil, the startup
+ ;; configuration can't be applied, so do
+ ;; something to get a VM buffer on the screen
+ (if vm-mutable-window-configuration
+ (vm-display nil nil (list this-command)
+ (list (or this-command 'vm) 'startup))
+ (save-excursion
+ (switch-to-buffer (or vm-summary-buffer
+ vm-presentation-buffer
+ (current-buffer))))))
+
+ ;; check interactive-p so as not to bog the user down if they
+ ;; run this function from within another function.
+ (when (and (vm-interactive-p)
+ (not vm-startup-message-displayed))
+ (vm-display-startup-message)
+ (vm-inform 5 blurb))))
+
+;;;###autoload
+(defun vm-visit-virtual-folder-other-frame (folder-name &optional read-only)
+ "Like vm-visit-virtual-folder, but run in a newly created frame."
+ (interactive
+ (let ((last-command last-command)
+ (this-command this-command))
+ (vm-session-initialization)
+ (list
+ (vm-read-string (format "Visit%s virtual folder in other frame: "
+ (if current-prefix-arg " read only" ""))
+ vm-virtual-folder-alist)
+ current-prefix-arg)))
+ (vm-session-initialization)
+ (if (vm-multiple-frames-possible-p)
+ (vm-goto-new-frame 'folder))
+ (let ((vm-frame-per-folder nil)
+ (vm-search-other-frames nil))
+ (vm-visit-virtual-folder folder-name read-only))
+ (if (vm-multiple-frames-possible-p)
+ (vm-set-hooks-for-frame-deletion)))
+
+;;;###autoload
+(defun vm-visit-virtual-folder-other-window (folder-name &optional read-only)
+ "Like vm-visit-virtual-folder, but run in a different window."
+ (interactive
+ (let ((last-command last-command)
+ (this-command this-command))
+ (vm-session-initialization)
+ (list
+ (vm-read-string (format "Visit%s virtual folder in other window: "
+ (if current-prefix-arg " read only" ""))
+ vm-virtual-folder-alist)
+ current-prefix-arg)))
+ (vm-session-initialization)
+ (if (one-window-p t)
+ (split-window))
+ (other-window 1)
+ (let ((vm-frame-per-folder nil)
+ (vm-search-other-frames nil))
+ (vm-visit-virtual-folder folder-name read-only)))
+
+;;;###autoload
+(defun vm-mail (&optional to subject)
+ "Send a mail message from within VM, or from without.
+Optional argument TO is a string that should contain a comma separated
+recipient list."
+ (interactive)
+ (vm-session-initialization)
+ (vm-check-for-killed-folder)
+ (let ((guess (when (null to)
+ (vm-select-recipient-from-sender))))
+ (vm-select-folder-buffer-if-possible)
+ (vm-check-for-killed-summary)
+ (vm-mail-internal :to to :guessed-to guess :subject subject)
+ (run-hooks 'vm-mail-hook)
+ (run-hooks 'vm-mail-mode-hook)))
+
+;;;###autoload
+(defun vm-mail-other-frame (&optional to)
+ "Like vm-mail, but run in a newly created frame.
+Optional argument TO is a string that should contain a comma separated
+recipient list."
+ (interactive)
+ (vm-session-initialization)
+ (when (null to)
+ (setq to (vm-select-recipient-from-sender)))
+ (if (vm-multiple-frames-possible-p)
+ (vm-goto-new-frame 'composition))
+ (let ((vm-frame-per-composition nil)
+ (vm-search-other-frames nil))
+ (vm-mail to))
+ (if (vm-multiple-frames-possible-p)
+ (vm-set-hooks-for-frame-deletion)))
+
+;;;###autoload
+(defun vm-mail-other-window (&optional to)
+ "Like vm-mail, but run in a different window.
+Optional argument TO is a string that should contain a comma separated
+recipient list."
+ (interactive)
+ (vm-session-initialization)
+ (when (null to)
+ (setq to (vm-select-recipient-from-sender)))
+ (if (one-window-p t)
+ (split-window))
+ (other-window 1)
+ (let ((vm-frame-per-composition nil)
+ (vm-search-other-frames nil))
+ (vm-mail to)))
+
+(fset 'vm-folders-summary-mode 'vm-mode)
+(put 'vm-folders-summary-mode 'mode-class 'special)
+
+;;;###autoload
+(defun vm-folders-summarize (&optional display raise)
+ "Generate a summary of the folders in your folder directories.
+Set `vm-folders-summary-directories' to specify the folder directories.
+Press RETURN or click mouse button 2 on an entry in the folders
+summary buffer to select a folder."
+ (interactive "p\np")
+ (vm-session-initialization)
+ (vm-check-for-killed-summary)
+ (if (not (featurep 'berkeley-db))
+ (error "Berkeley DB support needed to run this command"))
+ (if (null vm-folders-summary-database)
+ (error "'vm-folders-summary-database' must be non-nil to run this command"))
+ (if (null vm-folders-summary-buffer)
+ (let ((folder-buffer (and (eq major-mode 'vm-mode)
+ (current-buffer)))
+ (summary-buffer-name "VM Folders Summary"))
+ (setq vm-folders-summary-buffer
+ (or (get-buffer summary-buffer-name)
+ (vm-generate-new-multibyte-buffer summary-buffer-name)))
+ (save-excursion
+ (set-buffer vm-folders-summary-buffer)
+ (abbrev-mode 0)
+ (auto-fill-mode 0)
+ (vm-fsfemacs-nonmule-display-8bit-chars)
+ (if (fboundp 'buffer-disable-undo)
+ (buffer-disable-undo (current-buffer))
+ ;; obfuscation to make the v19 compiler not whine
+ ;; about obsolete functions.
+ (let ((x 'buffer-flush-undo))
+ (funcall x (current-buffer))))
+ (vm-folders-summary-mode-internal))
+ (vm-make-folders-summary-associative-hashes)
+ (vm-do-folders-summary)))
+ ;; if this command was run from a VM related buffer, select
+ ;; the folder buffer in the folders summary, but only if that
+ ;; folder has an entry there.
+ (and vm-mail-buffer
+ (vm-check-for-killed-folder))
+ (save-excursion
+ (and vm-mail-buffer
+ (vm-select-folder-buffer-and-validate 0 (vm-interactive-p)))
+ (vm-check-for-killed-summary)
+ (let ((folder-buffer (and (eq major-mode 'vm-mode)
+ (current-buffer)))
+ fs )
+ (if (or (null vm-folders-summary-hash) (null folder-buffer)
+ (null buffer-file-name))
+ nil
+ (setq fs (symbol-value (intern-soft (vm-make-folders-summary-key
+ buffer-file-name)
+ vm-folders-summary-hash)))
+ (if (null fs)
+ nil
+ (vm-mark-for-folders-summary-update buffer-file-name)
+ (set-buffer vm-folders-summary-buffer)
+ (setq vm-mail-buffer folder-buffer)))))
+ (if display
+ (save-excursion
+ (vm-goto-new-folders-summary-frame-maybe)
+ (vm-display vm-folders-summary-buffer t
+ '(vm-folders-summarize)
+ (list this-command) (not raise))
+ ;; need to do this after any frame creation because the
+ ;; toolbar sets frame-specific height and width specifiers.
+ (set-buffer vm-folders-summary-buffer)
+ (vm-toolbar-install-or-uninstall-toolbar))
+ (vm-display nil nil '(vm-folders-summarize)
+ (list this-command)))
+ (vm-update-summary-and-mode-line))
+
+(defvar mail-reply-action)
+(defvar mail-send-actions)
+(defvar mail-return-action)
+
+;;;###autoload
+(defun vm-compose-mail (&optional to subject other-headers continue
+ switch-function yank-action
+ send-actions return-action &rest ignored)
+ (interactive)
+ (vm-session-initialization)
+ (if continue
+ (vm-continue-composing-message)
+ (let ((buffer (vm-mail-internal
+ :buffer-name (if to
+ (format "message to %s"
+ (vm-truncate-roman-string to 20))
+ nil)
+ :to to :subject subject)))
+ (goto-char (point-min))
+ (re-search-forward (concat "^" mail-header-separator "$"))
+ (beginning-of-line)
+ (while other-headers
+ (insert (car (car other-headers)))
+ (while (eq (char-syntax (char-before (point))) ?\ )
+ (delete-char -1))
+ (while (eq (char-before (point)) ?:)
+ (delete-char -1))
+ (insert ": " (cdr (car other-headers)))
+ (if (not (eq (char-before (point)) ?\n))
+ (insert "\n"))
+ (setq other-headers (cdr other-headers)))
+ (cond ((null to)
+ (mail-position-on-field "To"))
+ ((null subject)
+ (mail-position-on-field "Subject"))
+ (t
+ (mail-text)))
+ (funcall (or switch-function (function switch-to-buffer))
+ (current-buffer))
+ (if yank-action
+ (save-excursion
+ (mail-text)
+ (apply (car yank-action) (cdr yank-action))
+ (push-mark (point))
+ (mail-text)
+ (cond (mail-citation-hook (run-hooks 'mail-citation-hook))
+ (mail-yank-hooks (run-hooks 'mail-yank-hooks))
+ (t (vm-mail-yank-default)))))
+ (make-local-variable 'mail-send-actions)
+ (setq mail-send-actions send-actions)
+ (make-local-variable 'mail-return-action)
+ (setq mail-return-action return-action))))
+
+;;;###autoload
+(defun vm-submit-bug-report (&optional pre-hooks post-hooks)
+ "Submit a bug report, with pertinent information to the VM bug list."
+ (interactive)
+ (require 'reporter)
+ (vm-session-initialization)
+ ;; Use VM to send the bug report. Could be trouble if vm-mail
+ ;; is what the user wants to complain about. But most of the
+ ;; time we'll be fine and users like to use MIME to attach
+ ;; stuff to the reports.
+ (let ((reporter-mailer '(vm-mail))
+ (mail-user-agent 'vm-user-agent)
+ varlist (errors 0))
+ (setq varlist (apropos-internal "^\\(vm\\|vmpc\\)-" 'user-variable-p)
+ varlist (sort varlist
+ (lambda (v1 v2)
+ (string-lessp (format "%s" v1) (format "%s" v2)))))
+ (when (and (eq vm-mime-text/html-handler 'emacs-w3m)
+ (boundp 'emacs-w3m-version))
+ (nconc varlist (list 'emacs-w3m-version 'w3m-version
+ 'w3m-goto-article-function)))
+ (let ((fill-column (1- (window-width))) ; turn off auto-fill
+ (mail-user-agent 'message-user-agent) ; use the default
+ ; mail-user-agent for bug reports
+ (vars-to-delete
+ '(vm-auto-folder-alist ; a bit private
+ vm-mail-folder-alist ; ditto
+ vm-virtual-folder-alist ; ditto
+ ;; vm-mail-fcc-default - is this private?
+ vmpc-actions vmpc-conditions
+ vmpc-actions-alist vmpc-reply-alist vmpc-forward-alist
+ vmpc-resend-alist vmpc-newmail-alist vmpc-automorph-alist
+ ;; email addresses
+ vm-mail-header-from
+ vm-mail-return-receipt-to
+ vm-summary-uninteresting-senders
+ ;; obsolete-variables
+ vm-imap-server-list
+ ))
+ ;; delete any passwords stored in maildrop strings
+ (vm-spool-files
+ (condition-case nil
+ (if (listp (car vm-spool-files))
+ (vm-mapcar
+ (lambda (elem-xyz)
+ (vm-mapcar (function vm-maildrop-sans-personal-info)
+ elem-xyz)))
+ (vm-mapcar (function vm-maildrop-sans-personal-info)
+ vm-spool-files))
+ (error (vm-increment errors) vm-spool-files)))
+ (vm-pop-folder-alist
+ (condition-case nil
+ (vm-maildrop-alist-sans-personal-info
+ vm-pop-folder-alist)
+ (error (vm-increment errors) vm-pop-folder-alist)))
+ ;; (vm-imap-server-list
+ ;; (with-no-warnings
+ ;; (condition-case nil
+ ;; (vm-mapcar (function vm-maildrop-sans-personal-info)
+ ;; vm-imap-server-list)
+ ;; (error (vm-increment errors) vm-imap-server-list))))
+ (vm-imap-account-alist
+ (condition-case nil
+ (vm-maildrop-alist-sans-personal-info
+ vm-imap-account-alist)
+ (error (vm-increment errors) vm-imap-account-alist)))
+ (vm-pop-auto-expunge-alist
+ (condition-case nil
+ (vm-maildrop-alist-sans-personal-info
+ vm-pop-auto-expunge-alist)
+ (error (vm-increment errors) vm-pop-auto-expunge-alist)))
+ (vm-imap-auto-expunge-alist
+ (condition-case nil
+ (vm-maildrop-alist-sans-personal-info
+ vm-imap-auto-expunge-alist)
+ (error (vm-increment errors) vm-imap-auto-expunge-alist))))
+ (while vars-to-delete
+ (setq varlist (delete (car vars-to-delete) varlist)
+ vars-to-delete (cdr vars-to-delete)))
+ ;; see what the user had loaded
+ (setq varlist (append (list 'features) varlist))
+ (delete-other-windows)
+ (reporter-submit-bug-report
+ vm-maintainer-address ; address
+ (concat "VM " (vm-version)) ; pkgname
+ varlist ; varlist
+ pre-hooks ; pre-hooks
+ post-hooks ; post-hooks
+ (concat ; salutation
+ "INSTRUCTIONS:
+- Please change the Subject header to a concise bug description.
+
+- In this report, remember to cover the basics, that is, what you
+ expected to happen and what in fact did happen and how to reproduce it.
+
+- You may attach sample messages or attachments that can be used to
+ reproduce the problem.
+
+- Mail sent to viewmail-bugs@nongnu.org is only viewed by VM
+ maintainers and it is not made public.
+
+- You may remove these instructions and other stuff which is unrelated
+ to the bug from your message.
+"
+ (if (> errors 0)
+ "
+- The raw definitions for some of the mail configurations are included
+ below because there were errors in cleaning them. Please replace any
+ sensitive information by xxxx."))
+ )
+ (goto-char (point-min))
+ (mail-position-on-field "Subject"))))
+
+(defun vm-edit-init-file ()
+ "Edit the `vm-init-file'."
+ (interactive)
+ (find-file-other-frame vm-init-file))
+
+(defun vm-check-emacs-version ()
+ "Checks the version of Emacs and gives an error if it is unsupported."
+ (cond ((and vm-xemacs-p (< emacs-major-version 21))
+ (error "VM %s must be run on XEmacs 21 or a later version."
+ (vm-version)))
+ ((and vm-fsfemacs-p (< emacs-major-version 21))
+ (error "VM %s must be run on GNU Emacs 21 or a later version."
+ (vm-version)))))
+
+;; This function is now defunct. USR, 2011-11-12
+
+;; (defun vm-set-debug-flags ()
+;; (or stack-trace-on-error
+;; debug-on-error
+;; (setq stack-trace-on-error
+;; '(
+;; wrong-type-argument
+;; wrong-number-of-arguments
+;; args-out-of-range
+;; void-function
+;; void-variable
+;; invalid-function
+;; ))))
+
+(defun vm-toggle-thread-operations ()
+ "Toggle the variable `vm-enable-thread-operations'.
+
+If enabled, VM operations on root messages of collapsed threads
+will apply to all the messages in the threads. If disabled, VM
+operations only apply to individual messages.
+
+\"Operations\" in this context include deleting, saving, setting
+attributes, adding/deleting labels etc."
+ (interactive)
+ (setq vm-enable-thread-operations (not vm-enable-thread-operations))
+ (if vm-enable-thread-operations
+ (vm-inform 5 "Thread operations enabled")
+ (vm-inform 5 "Thread operations disabled")))
+
+(defvar vm-postponed-folder)
+
+(defvar vm-drafts-exist nil)
+
+(defvar vm-ml-draft-count ""
+ "The current number of drafts in the `vm-postponed-folder'.")
+
+(defvar vm-postponed-folder)
+
+;;;###autoload
+(defun vm-update-draft-count ()
+ "Check number of postponed messages in folder `vm-postponed-folder'."
+ (let ((f (expand-file-name vm-postponed-folder vm-folder-directory)))
+ (if (or (not (file-exists-p f)) (= (nth 7 (file-attributes f)) 0))
+ (setq vm-drafts-exist nil)
+ (let ((mtime (nth 5 (file-attributes f))))
+ (when (not (equal vm-drafts-exist mtime))
+ (setq vm-drafts-exist mtime)
+ (setq vm-ml-draft-count (format "%d postponed"
+ (vm-count-messages-in-file f))))))))
+
+;;;###autoload
+(defun vm-session-initialization ()
+ "If this is the first time VM has been run in this Emacs session,
+do some necessary preparations. Otherwise, update the count of
+draft messages."
+ ;; (vm-set-debug-flags)
+ (if (or (not (boundp 'vm-session-beginning))
+ vm-session-beginning)
+ (progn
+ (vm-check-emacs-version)
+ (require 'vm-macro)
+ (require 'vm-vars)
+ (require 'vm-misc)
+ (require 'vm-message)
+ (require 'vm-minibuf)
+ (require 'vm-motion)
+ (require 'vm-page)
+ (require 'vm-mouse)
+ (require 'vm-summary)
+ (require 'vm-summary-faces)
+ (require 'vm-undo)
+ (require 'vm-mime)
+ (require 'vm-folder)
+ (require 'vm-toolbar)
+ (require 'vm-window)
+ (require 'vm-menu)
+ (require 'vm-rfaddons)
+ ;; The default loading of vm-pgg is disabled because it is an
+ ;; add-on. If and when it is integrated into VM, without advices
+ ;; and other add-on features, then it can be loaded by
+ ;; default. USR, 2010-01-14
+ ;; (if (locate-library "pgg")
+ ;; (require 'vm-pgg)
+ ;; (message "vm-pgg disabled since pgg is missing!"))
+ (add-hook 'kill-emacs-hook 'vm-garbage-collect-global)
+ (vm-load-init-file)
+ (when vm-enable-addons
+ (vm-rfaddons-infect-vm 0 vm-enable-addons))
+ (if (not vm-window-configuration-file)
+ (setq vm-window-configurations vm-default-window-configuration)
+ (or (vm-load-window-configurations vm-window-configuration-file)
+ (setq vm-window-configurations vm-default-window-configuration)))
+ (setq vm-buffers-needing-display-update (make-vector 29 0))
+ (setq vm-buffers-needing-undo-boundaries (make-vector 29 0))
+ (add-hook 'post-command-hook 'vm-add-undo-boundaries)
+ (if (if vm-xemacs-p
+ (find-face 'vm-monochrome-image)
+ (facep 'vm-monochrome-image))
+ nil
+ (make-face 'vm-monochrome-image)
+ (set-face-background 'vm-monochrome-image "white")
+ (set-face-foreground 'vm-monochrome-image "black"))
+ (if (or (not vm-fsfemacs-p)
+ ;; don't need this face under Emacs 21.
+ (fboundp 'image-type-available-p)
+ (facep 'vm-image-placeholder))
+ nil
+ (make-face 'vm-image-placeholder)
+ (if (fboundp 'set-face-stipple)
+ (set-face-stipple 'vm-image-placeholder
+ (list 16 16
+ (concat "UU\377\377UU\377\377UU\377\377"
+ "UU\377\377UU\377\377UU\377\377"
+ "UU\377\377UU\377\377")))))
+ (and (vm-mouse-support-possible-p)
+ (vm-mouse-install-mouse))
+ (and (vm-menu-support-possible-p)
+ vm-use-menus
+ (vm-menu-fsfemacs-menus-p)
+ (vm-menu-initialize-vm-mode-menu-map))
+ (setq vm-session-beginning nil)))
+ ;; check for postponed messages
+ (vm-update-draft-count))
+
+;;;###autoload
+(if (fboundp 'define-mail-user-agent)
+ (define-mail-user-agent 'vm-user-agent
+ (function vm-compose-mail) ; compose function
+ (function vm-mail-send-and-exit) ; send function
+ nil ; abort function (kill-buffer)
+ nil) ; hook variable (mail-send-hook)
+)
+
+(autoload 'reporter-submit-bug-report "reporter")
+(autoload 'timezone-make-date-sortable "timezone")
+(autoload 'rfc822-addresses "rfc822")
+(autoload 'mail-strip-quoted-names "mail-utils")
+(autoload 'mail-fetch-field "mail-utils")
+(autoload 'mail-position-on-field "mail-utils")
+(autoload 'mail-send "sendmail")
+(autoload 'mail-mode "sendmail")
+(autoload 'mail-extract-address-components "mail-extr")
+(autoload 'set-tapestry "tapestry")
+(autoload 'tapestry "tapestry")
+(autoload 'tapestry-replace-tapestry-element "tapestry")
+(autoload 'tapestry-nullify-tapestry-elements "tapestry")
+(autoload 'tapestry-remove-frame-parameters "tapestry")
+
+;;; vm.el ends here