Mercurial > hg > xemacs-beta
diff lisp/vm/vm-delete.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | ac2d302a0011 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/vm/vm-delete.el Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,290 @@ +;;; Delete and expunge commands for VM. +;;; Copyright (C) 1989, 1990, 1991, 1993, 1994, 1995 Kyle E. Jones +;;; +;;; 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +(provide 'vm-delete) + +(defun vm-delete-message (count) + "Add the `deleted' attribute to the current message. + +The message will be physically deleted from the current folder the next +time the current folder is expunged. + +With a prefix argument COUNT, the current message and the next +COUNT - 1 messages are deleted. A negative argument means the +the current message and the previous |COUNT| - 1 messages are +deleted. + +When invoked on marked messages (via vm-next-command-uses-marks), +only marked messages are deleted, other messages are ignored." + (interactive "p") + (if (interactive-p) + (vm-follow-summary-cursor)) + (vm-select-folder-buffer) + (vm-check-for-killed-summary) + (vm-error-if-folder-read-only) + (vm-error-if-folder-empty) + (let ((used-marks (eq last-command 'vm-next-command-uses-marks)) + (mlist (vm-select-marked-or-prefixed-messages count)) + (del-count 0)) + (while mlist + (if (not (vm-deleted-flag (car mlist))) + (progn + (vm-set-deleted-flag (car mlist) t) + (vm-increment del-count))) + (setq mlist (cdr mlist))) + (vm-display nil nil '(vm-delete-message vm-delete-message-backward) + (list this-command)) + (if (and used-marks (interactive-p)) + (if (zerop del-count) + (message "No messages deleted") + (message "%d message%s deleted" + del-count + (if (= 1 del-count) "" "s")))) + (vm-update-summary-and-mode-line) + (if (and vm-move-after-deleting (not used-marks)) + (let ((vm-circular-folders (and vm-circular-folders + (eq vm-move-after-deleting t)))) + (vm-next-message count t executing-kbd-macro))))) + +(defun vm-delete-message-backward (count) + "Like vm-delete-message, except the deletion direction is reversed." + (interactive "p") + (if (interactive-p) + (vm-follow-summary-cursor)) + (vm-delete-message (- count))) + +(defun vm-undelete-message (count) + "Remove the `deleted' attribute from the current message. + +With a prefix argument COUNT, the current message and the next +COUNT - 1 messages are undeleted. A negative argument means the +the current message and the previous |COUNT| - 1 messages are +deleted. + +When invoked on marked messages (via vm-next-command-uses-marks), +only marked messages are undeleted, other messages are ignored." + (interactive "p") + (if (interactive-p) + (vm-follow-summary-cursor)) + (vm-select-folder-buffer) + (vm-check-for-killed-summary) + (vm-error-if-folder-read-only) + (vm-error-if-folder-empty) + (let ((used-marks (eq last-command 'vm-next-command-uses-marks)) + (mlist (vm-select-marked-or-prefixed-messages count)) + (undel-count 0)) + (while mlist + (if (vm-deleted-flag (car mlist)) + (progn + (vm-set-deleted-flag (car mlist) nil) + (vm-increment undel-count))) + (setq mlist (cdr mlist))) + (if (and used-marks (interactive-p)) + (if (zerop undel-count) + (message "No messages undeleted") + (message "%d message%s undeleted" + undel-count + (if (= 1 undel-count) + "" "s")))) + (vm-display nil nil '(vm-undelete-message) '(vm-undelete-message)) + (vm-update-summary-and-mode-line) + (if (and vm-move-after-undeleting (not used-marks)) + (let ((vm-circular-folders (and vm-circular-folders + (eq vm-move-after-undeleting t)))) + (vm-next-message count t executing-kbd-macro))))) + +(defun vm-kill-subject () + "Delete all messages with the same subject as the current message. +Message subjects are compared after ignoring parts matched by +the variables vm-subject-ignored-prefix and vm-subject-ignored-suffix." + (interactive) + (vm-follow-summary-cursor) + (vm-select-folder-buffer) + (vm-check-for-killed-summary) + (vm-error-if-folder-read-only) + (vm-error-if-folder-empty) + (let ((subject (vm-so-sortable-subject (car vm-message-pointer))) + (mp vm-message-list) + (n 0) + (case-fold-search t)) + (while mp + (if (and (not (vm-deleted-flag (car mp))) + (string-equal subject (vm-so-sortable-subject (car mp)))) + (progn + (vm-set-deleted-flag (car mp) t) + (vm-increment n))) + (setq mp (cdr mp))) + (and (interactive-p) + (if (zerop n) + (message "No messages deleted.") + (message "%d message%s deleted" n (if (= n 1) "" "s"))))) + (vm-display nil nil '(vm-kill-subject) '(vm-kill-subject)) + (vm-update-summary-and-mode-line)) + +(defun vm-expunge-folder (&optional shaddap) + "Expunge messages with the `deleted' attribute. +For normal folders this means that the deleted messages are +removed from the message list and the message contents are +removed from the folder buffer. + +For virtual folders, messages are removed from the virtual +message list. If virtual mirroring is in effect for the virtual +folder, the corresponding real messages are also removed from real +message lists and the message contents are removed from real folders. + +When invoked on marked messages (via vm-next-command-uses-marks), +only messages both marked and deleted are expunged, other messages are +ignored." + (interactive) + (vm-select-folder-buffer) + (vm-check-for-killed-summary) + (vm-error-if-folder-read-only) + ;; do this so we have a clean slate. code below depends on the + ;; fact that the numbering redo start point begins as nil in + ;; all folder buffers. + (vm-update-summary-and-mode-line) + (if (not shaddap) + (vm-unsaved-message "Expunging...")) + (let ((use-marks (eq last-command 'vm-next-command-uses-marks)) + (mp vm-message-list) + (virtual (eq major-mode 'vm-virtual-mode)) + (buffers-altered (make-vector 29 0)) + prev virtual-messages) + (while mp + (cond + ((and (vm-deleted-flag (car mp)) + (or (not use-marks) + (vm-mark-of (car mp)))) + ;; remove the message from the thread tree. + (if vm-thread-obarray + (vm-unthread-message (vm-real-message-of (car mp)))) + ;; expunge from the virtual side first, removing all + ;; references to this message before actually removing + ;; the message itself. + (cond + ((setq virtual-messages (vm-virtual-messages-of (car mp))) + (let (vms prev curr) + (if virtual + (setq vms (cons (vm-real-message-of (car mp)) + (vm-virtual-messages-of (car mp)))) + (setq vms (vm-virtual-messages-of (car mp)))) + (while vms + (save-excursion + (set-buffer (vm-buffer-of (car vms))) + (setq prev (vm-reverse-link-of (car vms)) + curr (or (cdr prev) vm-message-list)) + (intern (buffer-name) buffers-altered) + (vm-set-numbering-redo-start-point (or prev t)) + (vm-set-summary-redo-start-point (or prev t)) + (if (eq vm-message-pointer curr) + (setq vm-system-state nil + vm-message-pointer (or prev (cdr curr)))) + (if (eq vm-last-message-pointer curr) + (setq vm-last-message-pointer nil)) + ;; lock out interrupts to preserve message-list integrity + (let ((inhibit-quit t)) + ;; vm-clear-expunge-invalidated-undos uses + ;; this to recognize expunged messages. + ;; If this stuff is mirrored we'll be + ;; setting this value multiple times if there + ;; are multiple virtual messages referencing + ;; the underlying real message. Harmless. + (vm-set-deleted-flag-of (car curr) 'expunged) + ;; disable summary any summary update that may have + ;; already been scheduled. + (vm-set-su-start-of (car curr) nil) + (vm-increment vm-modification-counter) + (if (null prev) + (progn + (setq vm-message-list (cdr vm-message-list)) + (and (cdr curr) + (vm-set-reverse-link-of (car (cdr curr)) nil))) + (setcdr prev (cdr curr)) + (and (cdr curr) + (vm-set-reverse-link-of (car (cdr curr)) prev))) + (vm-set-virtual-messages-of (car mp) (cdr vms)) + (vm-set-buffer-modified-p t))) + (setq vms (cdr vms)))))) + (cond + ((or (not virtual-messages) + (not virtual)) + (and (not virtual-messages) virtual + (vm-set-virtual-messages-of + (vm-real-message-of (car mp)) + (delq (car mp) (vm-virtual-messages-of + (vm-real-message-of (car mp)))))) + (if (eq vm-message-pointer mp) + (setq vm-system-state nil + vm-message-pointer (or prev (cdr mp)))) + (if (eq vm-last-message-pointer mp) + (setq vm-last-message-pointer nil)) + (intern (buffer-name) buffers-altered) + (if (null vm-numbering-redo-start-point) + (progn + (vm-set-numbering-redo-start-point (or prev t)) + (vm-set-summary-redo-start-point (or prev t)))) + ;; lock out interrupt to preserve message list integrity + (let ((inhibit-quit t)) + (if (null prev) + (progn (setq vm-message-list (cdr vm-message-list)) + (and (cdr mp) + (vm-set-reverse-link-of (car (cdr mp)) nil))) + (setcdr prev (cdr mp)) + (and (cdr mp) (vm-set-reverse-link-of (car (cdr mp)) prev))) + ;; vm-clear-expunge-invalidated-undos uses this to recognize + ;; expunged messages. + (vm-set-deleted-flag-of (car mp) 'expunged) + ;; disable summary any summary update that may have + ;; already been scheduled. + (vm-set-su-start-of (car mp) nil) + (vm-set-buffer-modified-p t) + (vm-increment vm-modification-counter)))) + (if (eq (vm-attributes-of (car mp)) + (vm-attributes-of (vm-real-message-of (car mp)))) + (save-excursion + (set-buffer (vm-buffer-of (vm-real-message-of (car mp)))) + (vm-save-restriction + (widen) + (let ((buffer-read-only nil)) + (delete-region (vm-start-of (vm-real-message-of (car mp))) + (vm-end-of (vm-real-message-of (car mp))))))))) + (t (setq prev mp))) + (setq mp (cdr mp))) + (vm-display nil nil '(vm-expunge-folder) '(vm-expunge-folder)) + (cond + (buffers-altered + (save-excursion + (mapatoms + (function + (lambda (buffer) + (set-buffer (symbol-name buffer)) + (if (null vm-system-state) + (if (null vm-message-pointer) + ;; folder is now empty + (progn (setq vm-folder-type nil) + (vm-update-summary-and-mode-line)) + (vm-preview-current-message)) + (vm-update-summary-and-mode-line)) + (if (not (eq major-mode 'vm-virtual-mode)) + (setq vm-message-order-changed + (or vm-message-order-changed + vm-message-order-header-present))) + (vm-clear-expunge-invalidated-undos))) + buffers-altered)) + (if (not shaddap) + (message "Deleted messages expunged."))) + (t (message "No messages are flagged for deletion.")))))