X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=wl%2Fwl-summary.el;h=ba42408a43afe71f78274b8ecca79ebad60223b2;hb=52061841b6997afec3a3108019c9362c35e4864b;hp=94878cba60a1c3c303a6a65562a977b035f2abf3;hpb=bd64e2f6e6a10951b21ffbc339a5f922995f4032;p=elisp%2Fwanderlust.git diff --git a/wl/wl-summary.el b/wl/wl-summary.el index 94878cb..ba42408 100644 --- a/wl/wl-summary.el +++ b/wl/wl-summary.el @@ -209,6 +209,12 @@ subject-string)) (defun wl-summary-default-from (from) + "Instance of `wl-summary-from-function'. +Ordinarily returns the sender name. Returns recipient names if (1) +summary's folder name matches with `wl-summary-showto-folder-regexp' +and (2) sender address is yours. + +See also variable `wl-use-petname'." (let (retval tos ng) (unless (and (eq major-mode 'wl-summary-mode) @@ -400,7 +406,6 @@ (define-key wl-summary-mode-map "g" 'wl-summary-goto-folder) (define-key wl-summary-mode-map "G" 'wl-summary-goto-folder-sticky) (define-key wl-summary-mode-map "c" 'wl-summary-mark-as-read-all) -; (define-key wl-summary-mode-map "D" 'wl-summary-drop-unsync) (define-key wl-summary-mode-map "a" 'wl-summary-reply) (define-key wl-summary-mode-map "A" 'wl-summary-reply-with-citation) @@ -416,10 +421,8 @@ (define-key wl-summary-mode-map "p" 'wl-summary-prev) (define-key wl-summary-mode-map "N" 'wl-summary-down) (define-key wl-summary-mode-map "P" 'wl-summary-up) -;;;(define-key wl-summary-mode-map "w" 'wl-draft) (define-key wl-summary-mode-map "w" 'wl-summary-write) (define-key wl-summary-mode-map "W" 'wl-summary-write-current-folder) -;;;(define-key wl-summary-mode-map "e" 'wl-draft-open-file) (define-key wl-summary-mode-map "e" 'wl-summary-save) (define-key wl-summary-mode-map "\C-c\C-o" 'wl-jump-to-draft-buffer) (define-key wl-summary-mode-map "\C-c\C-a" 'wl-addrmgr) @@ -472,6 +475,7 @@ (define-key wl-summary-mode-map "d" 'wl-summary-delete) (define-key wl-summary-mode-map "u" 'wl-summary-unmark) (define-key wl-summary-mode-map "U" 'wl-summary-unmark-all) + (define-key wl-summary-mode-map "D" 'wl-summary-erase) ;; thread commands (define-key wl-summary-mode-map "t" (make-sparse-keymap)) @@ -507,6 +511,7 @@ (define-key wl-summary-mode-map "m?" 'wl-summary-target-mark-pick) (define-key wl-summary-mode-map "m#" 'wl-summary-target-mark-print) (define-key wl-summary-mode-map "m|" 'wl-summary-target-mark-pipe) + (define-key wl-summary-mode-map "mD" 'wl-summary-target-mark-erase) ;; region commands (define-key wl-summary-mode-map "r" (make-sparse-keymap)) @@ -605,16 +610,15 @@ If optional USE-CACHE is non-nil, use cache if exists." "Re-edit current message. If ARG is non-nil, Supersedes message" (interactive "P") + (wl-summary-toggle-disp-msg 'off) (if arg (wl-summary-supersedes-message) (if (string= (wl-summary-buffer-folder-name) wl-draft-folder) - (if (wl-summary-message-number) - (progn - (wl-draft-reedit (wl-summary-message-number)) - (if (wl-message-news-p) - (mail-position-on-field "Newsgroups") - (mail-position-on-field "To")) - (delete-other-windows))) + (when (wl-summary-message-number) + (wl-draft-reedit (wl-summary-message-number)) + (if (wl-message-news-p) + (mail-position-on-field "Newsgroups") + (mail-position-on-field "To"))) (wl-draft-edit-string (wl-summary-message-string))))) (defun wl-summary-resend-bounced-mail () @@ -623,6 +627,7 @@ This only makes sense if the current message is a bounce message which contains some mail you have written but has been bounced back to you." (interactive) + (wl-summary-toggle-disp-msg 'off) (save-excursion (wl-summary-set-message-buffer-or-redisplay) (set-buffer (wl-message-get-original-buffer)) @@ -864,7 +869,7 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'." (defun wl-summary-get-list-info (entity) "Returns (\"ML-name\" . ML-count) of ENTITY." - (let (sequence ml-name ml-count subject return-path) + (let (sequence ml-name ml-count subject return-path delivered-to mailing-list) (setq sequence (elmo-msgdb-overview-entity-get-extra-field entity "x-sequence") ml-name (or (elmo-msgdb-overview-entity-get-extra-field @@ -891,6 +896,16 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'." (progn (or ml-name (setq ml-name (match-string 1 return-path))) (or ml-count (setq ml-count (match-string 2 return-path))))) + (and (setq delivered-to + (elmo-msgdb-overview-entity-get-extra-field + entity "delivered-to")) + (string-match "^mailing list \\([^@]+\\)@" delivered-to) + (or ml-name (setq ml-name (match-string 1 delivered-to)))) + (and (setq mailing-list + (elmo-msgdb-overview-entity-get-extra-field + entity "mailing-list")) + (string-match "\\(^\\|; \\)contact \\([^@]+\\)-[^-@]+@" mailing-list) ; *-help@, *-owner@, etc. + (or ml-name (setq ml-name (match-string 2 mailing-list)))) (cons (and ml-name (car (split-string ml-name " "))) (and ml-count (string-to-int ml-count))))) @@ -898,12 +913,13 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'." "Compare entity X and Y by mailing-list info." (let* ((list-info-x (wl-summary-get-list-info x)) (list-info-y (wl-summary-get-list-info y))) - (if (equal list-info-x list-info-y) - (wl-summary-overview-entity-compare-by-date x y) - (if (string= (car list-info-x) (car list-info-y)) + (if (equal (car list-info-x) (car list-info-y)) + (if (equal (cdr list-info-x) (cdr list-info-y)) + (wl-summary-overview-entity-compare-by-date x y) (< (or (cdr list-info-x) 0) - (or (cdr list-info-y) 0)) - (string< (car list-info-x) (car list-info-y)))))) + (or (cdr list-info-y) 0))) + (string< (or (car list-info-x) "") + (or (car list-info-y) ""))))) (defun wl-summary-sort-by-date () (interactive) @@ -1067,7 +1083,8 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'." (if (or wl-summary-buffer-refile-list wl-summary-buffer-copy-list wl-summary-buffer-delete-list) - (if (y-or-n-p "Marks remain to be executed. Execute them? ") + (if (y-or-n-p (format "Execute remaining marks in %s? " + (wl-summary-buffer-folder-name))) (progn (wl-summary-exec) (if (or wl-summary-buffer-refile-list @@ -1106,7 +1123,7 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'." (elmo-folder-commit wl-summary-buffer-elmo-folder) (elmo-folder-check wl-summary-buffer-elmo-folder) (if wl-use-scoring (wl-score-save)) - (if (interactive-p) (message "Saving summary status...done."))) + (if (interactive-p) (message "Saving summary status...done"))) (defun wl-summary-force-exit () "Exit current summary. Buffer is deleted even the buffer is sticky." @@ -2455,7 +2472,11 @@ If ARG, without confirm." (if (file-exists-p view) (setq wl-summary-buffer-view (wl-summary-load-file-object view)) - (setq wl-summary-buffer-view wl-summary-default-view)) + (setq wl-summary-buffer-view + (or (wl-get-assoc-list-value + wl-summary-default-view-alist + (elmo-folder-name-internal folder)) + wl-summary-default-view))) (wl-thread-resume-entity folder) (wl-summary-open-folder folder)) (setq wl-summary-buffer-view @@ -2641,7 +2662,6 @@ If ARG, without confirm." wl-summary-alike-hashtb))) (defun wl-summary-insert-headers (overview func mime-decode) - (message "Creating subject cache...") (let (ov this last alike) (buffer-disable-undo (current-buffer)) (make-local-variable 'wl-summary-alike-hashtb) @@ -2652,7 +2672,7 @@ If ARG, without confirm." (setq this (funcall func ov)) (and this (setq this (std11-unfold-string this))) (if (equal last this) - (wl-append alike (list ov)) + (setq alike (cons ov alike)) (when last (wl-summary-put-alike alike) (insert last ?\n)) @@ -2666,54 +2686,59 @@ If ARG, without confirm." elmo-mime-charset) (when (eq mime-decode 'mime) (eword-decode-region (point-min) (point-max)))) - (message "Creating subject cache...done") (run-hooks 'wl-summary-insert-headers-hook))) (defun wl-summary-search-by-subject (entity overview) (let ((summary-buf (current-buffer)) (buf (get-buffer-create wl-summary-search-buf-name)) (folder-name (wl-summary-buffer-folder-name)) - match founds found-entity) + match founds cur result) (with-current-buffer buf (let ((case-fold-search t)) (when (or (not (string= wl-summary-search-buf-folder-name folder-name)) (zerop (buffer-size))) (setq wl-summary-search-buf-folder-name folder-name) + (message "Creating subject cache...") (wl-summary-insert-headers overview (function (lambda (x) (funcall wl-summary-subject-filter-function - (elmo-msgdb-overview-entity-get-subject-no-decode x)))) - t)) + (elmo-msgdb-overview-entity-get-subject-no-decode x)))) + t) + (message "Creating subject cache...done")) (setq match (funcall wl-summary-subject-filter-function (elmo-msgdb-overview-entity-get-subject entity))) (if (string= match "") (setq match "\n")) - (goto-char (point-min)) - (while (and (not founds) - (not (= (point) (point-max))) - (search-forward match nil t)) + (goto-char (point-max)) + (while (and (null result) + (not (= (point) (point-min))) + (search-backward match nil t)) ;; check exactly match - (when (and (eolp) - (= (point-at-bol) - (match-beginning 0))) - (setq found-entity (wl-summary-get-alike)) - (if (and found-entity - ;; Is founded entity myself or children? - (not (string= - (elmo-msgdb-overview-entity-get-id entity) - (elmo-msgdb-overview-entity-get-id - (car found-entity)))) - (with-current-buffer summary-buf + (when (and (bolp) (= (point-at-eol)(match-end 0))) + (setq founds (wl-summary-get-alike)) + (with-current-buffer summary-buf + (while founds + (when (and + ;; the first element of found-entity list exists on + ;; thread tree. + (wl-thread-get-entity + (elmo-msgdb-overview-entity-get-number + (car founds))) + ;; message id is not same as myself. + (not (string= + (elmo-msgdb-overview-entity-get-id entity) + (elmo-msgdb-overview-entity-get-id (car founds)))) + ;; not a descendant. (not (wl-thread-descendant-p (elmo-msgdb-overview-entity-get-number entity) (elmo-msgdb-overview-entity-get-number - (car found-entity)))))) - ;; return matching entity - (setq founds found-entity)))) - (if founds - (car founds)))))) + (car founds))))) + (setq result (car founds) + founds nil)) + (setq founds (cdr founds)))))) + result)))) (defun wl-summary-insert-thread-entity (entity msgdb update &optional force-insert) @@ -2722,6 +2747,7 @@ If ARG, without confirm." parent-entity parent-number (case-fold-search t) + (depth 0) relatives anumber cur number overview2 cur-entity linked retval delayed-entity update-list entity-stack) (while entity @@ -2731,14 +2757,18 @@ If ARG, without confirm." parent-number (elmo-msgdb-overview-entity-get-number parent-entity)) (setq number (elmo-msgdb-overview-entity-get-number entity)) - ;; If thread loop detected, set parent as nil. (setq cur entity) + ;; If thread loop detected, set parent as nil. (while cur - (if (eq number (elmo-msgdb-overview-entity-get-number - (setq cur - (elmo-msgdb-get-parent-entity cur msgdb)))) + (setq anumber + (elmo-msgdb-overview-entity-get-number + (setq cur (elmo-msgdb-get-parent-entity cur msgdb)))) + (if (memq anumber relatives) (setq parent-number nil - cur nil))) + cur nil)) + (setq relatives (cons + (elmo-msgdb-overview-entity-get-number cur) + relatives))) (if (and parent-number (not (wl-thread-get-entity parent-number)) (not force-insert)) @@ -2792,26 +2822,29 @@ If ARG, without confirm." (overview-entity entity) (parent-id (elmo-msgdb-overview-entity-get-id parent-entity)) (number (elmo-msgdb-overview-entity-get-number entity)) - (parent-number (elmo-msgdb-overview-entity-get-number parent-entity))) + (parent-number (elmo-msgdb-overview-entity-get-number parent-entity)) + insert-line) (cond ((or (not parent-id) (string= this-id parent-id)) (goto-char (point-max)) - (beginning-of-line)) + (beginning-of-line) + (setq insert-line t)) ;; parent already exists in buffer. ((wl-summary-jump-to-msg parent-number) - (wl-thread-goto-bottom-of-sub-thread))) - (let ((inhibit-read-only t) - (buffer-read-only nil)) - (wl-summary-insert-line - (wl-summary-create-line - entity - parent-entity - nil - (elmo-msgdb-get-mark (wl-summary-buffer-msgdb) number) - (wl-thread-maybe-get-children-num number) - (wl-thread-make-indent-string thr-entity) - (wl-thread-entity-get-linked thr-entity)))))) + (wl-thread-goto-bottom-of-sub-thread) + (setq insert-line t))) + (when insert-line + (let (buffer-read-only) + (wl-summary-insert-line + (wl-summary-create-line + entity + parent-entity + nil + (elmo-msgdb-get-mark (wl-summary-buffer-msgdb) number) + (wl-thread-maybe-get-children-num number) + (wl-thread-make-indent-string thr-entity) + (wl-thread-entity-get-linked thr-entity))))))) (defun wl-summary-mark-as-unread (&optional number no-server-update @@ -2967,7 +3000,8 @@ If optional argument NUMBER is specified, mark message specified by NUMBER." (while (not (eobp)) (when (string= (wl-summary-temp-mark) mark) (setq msglist (cons (wl-summary-message-number) msglist))) - (forward-line 1))))))) + (forward-line 1)) + (nreverse msglist)))))) (defun wl-summary-exec () (interactive) @@ -2977,7 +3011,7 @@ If optional argument NUMBER is specified, mark message specified by NUMBER." (defun wl-summary-exec-region (beg end) (interactive "r") - (message "Collecting marks ...") + (message "Collecting marks...") (save-excursion (goto-char beg) (beginning-of-line) @@ -3006,7 +3040,7 @@ If optional argument NUMBER is specified, mark message specified by NUMBER." refile-len dst-msgs ; loop counter result) - (message "Executing ...") + (message "Executing...") (while dels (when (not (assq (car dels) wl-summary-buffer-refile-list)) (wl-append wl-summary-buffer-refile-list @@ -3097,7 +3131,7 @@ If optional argument NUMBER is specified, mark message specified by NUMBER." wl-message-buffer-cur-number))) (wl-summary-toggle-disp-msg 'off)) (set-buffer-modified-p nil) - (message (concat "Executing ... done" + (message (concat "Executing...done" (if (> refile-failures 0) (format " (%d refiling failed)" refile-failures) "") @@ -3106,6 +3140,45 @@ If optional argument NUMBER is specified, mark message specified by NUMBER." "") ".")))))) +(defun wl-summary-erase (&optional number) + "Erase message actually, without moving it to trash." + (interactive) + (if (elmo-folder-writable-p wl-summary-buffer-elmo-folder) + (let* ((buffer-num (wl-summary-message-number)) + (msg-num (or number buffer-num))) + (if (null msg-num) + (message "No message.") + (let* ((msgdb (wl-summary-buffer-msgdb)) + (entity (elmo-msgdb-overview-get-entity msg-num msgdb)) + (subject (elmo-delete-char + ?\n (or (elmo-msgdb-overview-entity-get-subject + entity) + wl-summary-no-subject-message)))) + (when (yes-or-no-p + (format "Erase \"%s\" without moving it to trash? " + (truncate-string subject 30))) + (wl-summary-unmark msg-num) + (elmo-folder-delete-messages wl-summary-buffer-elmo-folder + (list msg-num)) + (wl-summary-delete-messages-on-buffer (list msg-num)) + (save-excursion (wl-summary-sync nil "update")))))) + (message "Read-only folder."))) + +(defun wl-summary-target-mark-erase () + (interactive) + (if (elmo-folder-writable-p wl-summary-buffer-elmo-folder) + (if (null wl-summary-buffer-target-mark-list) + (message "No marked message.") + (when (yes-or-no-p + "Erase all marked messages without moving them to trash? ") + (elmo-folder-delete-messages wl-summary-buffer-elmo-folder + wl-summary-buffer-target-mark-list) + (wl-summary-delete-messages-on-buffer + wl-summary-buffer-target-mark-list) + (setq wl-summary-buffer-target-mark-list nil) + (save-excursion (wl-summary-sync nil "update")))) + (message "Read-only folder."))) + (defun wl-summary-read-folder (default &optional purpose ignore-error no-create init) (let ((fld (completing-read @@ -3114,14 +3187,7 @@ If optional argument NUMBER is specified, mark message specified by NUMBER." (or wl-folder-completion-function (if (memq 'read-folder wl-use-folder-petname) (wl-folder-get-entity-with-petname) - (let (alist) - (mapatoms - (lambda (atom) - (setq alist - (cons (list (elmo-string - (symbol-name atom))) alist))) - wl-folder-entity-hashtb) - alist))) + wl-folder-entity-hashtb)) nil nil (or init wl-default-spec) 'wl-read-folder-hist))) (if (or (string= fld wl-default-spec) @@ -3161,7 +3227,8 @@ If optional argument NUMBER is specified, mark message specified by NUMBER." (setq c (+ c (char-width (following-char))))) (and (> c len) (setq folder (concat " " folder))) (setq rs (point)) - (put-text-property rs re 'invisible t) + (when wl-summary-width + (put-text-property rs re 'invisible t)) (put-text-property rs re 'wl-summary-destination t) (goto-char re) (wl-highlight-refile-destination-string folder) @@ -3744,7 +3811,7 @@ If ARG, exit virtual folder." (setq skipped (cons (car mlist) skipped))) (setq mlist (cdr mlist))) (setq wl-summary-buffer-target-mark-list skipped) - (message "Prefetching... %d/%d message(s)." count length) + (message "Prefetching... %d/%d message(s)" count length) (set-buffer-modified-p nil)))) (defun wl-summary-target-mark-refile-subr (copy-or-refile) @@ -4135,7 +4202,6 @@ If ARG, exit virtual folder." (t (format "%dB" size))) ""))) -(defvar wl-summary-line-subject-minimum-length nil) (defun wl-summary-line-subject () (let (no-parent subject parent-raw-subject parent-subject) (if (string= wl-thr-indent-string "") @@ -4150,24 +4216,12 @@ If ARG, exit virtual folder." (setq parent-subject (if parent-raw-subject (elmo-delete-char ?\n parent-raw-subject))) - (setq subject - (if (or no-parent - (null parent-subject) - (not (wl-summary-subject-equal - subject parent-subject))) - (funcall wl-summary-subject-function subject) - "")) - (when (and wl-summary-line-subject-minimum-length - (< (string-width subject) - wl-summary-line-subject-minimum-length)) - (while (< (string-width subject) - wl-summary-line-subject-minimum-length) - (setq subject (concat subject " ")))) - (if (and (not wl-summary-width) - wl-summary-subject-length-limit) - (truncate-string subject - wl-summary-subject-length-limit) - subject))) + (if (or no-parent + (null parent-subject) + (not (wl-summary-subject-equal + subject parent-subject))) + (funcall wl-summary-subject-function subject) + ""))) (defun wl-summary-line-from () (elmo-delete-char ?\n @@ -4177,8 +4231,9 @@ If ARG, exit virtual folder." (defun wl-summary-line-list-info () (let ((list-info (wl-summary-get-list-info wl-message-entity))) - (if (and (car list-info) (cdr list-info)) - (format "(%s %05d)" (car list-info) (cdr list-info)) + (if (car list-info) + (format (if (cdr list-info) "(%s %05.0f)" "(%s)") + (car list-info) (cdr list-info)) ""))) (defun wl-summary-line-list-count () @@ -4189,7 +4244,8 @@ If ARG, exit virtual folder." (defun wl-summary-line-attached () (let ((content-type (elmo-msgdb-overview-entity-get-extra-field - wl-message-entity "content-type"))) + wl-message-entity "content-type")) + (case-fold-search t)) (if (and content-type (string-match "multipart/mixed" content-type)) "@" @@ -4364,7 +4420,8 @@ If ARG, exit virtual folder." (wl-summary-delete-all-temp-marks) (encode-coding-region (point-min) (point-max) - (or (mime-charset-to-coding-system charset 'LF) + (or (and wl-on-mule ; one in mcs-ltn1(apel<10.4) cannot take 2 arg. + (mime-charset-to-coding-system charset 'LF)) ;; Mule 2 doesn't have `*ctext*unix'. (mime-charset-to-coding-system charset))) (write-region-as-binary (point-min)(point-max) @@ -4656,6 +4713,7 @@ Return t if message exists." (save-excursion (set-buffer summary-buf) (wl-summary-delete-all-temp-marks))) + (wl-draft-reply-position wl-draft-reply-default-position) (run-hooks 'wl-mail-setup-hook))) (defun wl-summary-reply-with-citation (&optional arg) @@ -4663,6 +4721,7 @@ Return t if message exists." (when (wl-summary-reply arg t) (goto-char (point-max)) (wl-draft-yank-original) + (wl-draft-reply-position wl-draft-reply-default-position) (run-hooks 'wl-mail-setup-hook))) (defun wl-summary-jump-to-msg-by-message-id (&optional id) @@ -4865,11 +4924,9 @@ Reply to author if invoked with ARG." (wl-message-select-buffer wl-message-buffer) (set-buffer mes-buf) (goto-char (point-min)) - (unless wl-draft-use-frame - (split-window-vertically) - (other-window 1)) (when (setq mes-buf (wl-message-get-original-buffer)) (wl-draft-reply mes-buf arg summary-buf) + (wl-draft-reply-position wl-draft-reply-default-position) (unless without-setup-hook (run-hooks 'wl-mail-setup-hook))) t))) @@ -4939,9 +4996,6 @@ Use function list is `wl-summary-write-current-folder-functions'." (wl-summary-redisplay-internal folder number)) (setq mes-buf wl-message-buffer) (wl-message-select-buffer mes-buf) - (unless wl-draft-use-frame - (split-window-vertically) - (other-window 1)) ;; get original subject. (if summary-buf (save-excursion @@ -4986,7 +5040,7 @@ Use function list is `wl-summary-write-current-folder-functions'." (if downward (forward-line 1) (forward-line -1)) - (setq skip (or (string-match skip-tmark-regexp + (setq skip (or (string-match skip-tmark-regexp (save-excursion (wl-summary-temp-mark))) (and skip-pmark-regexp @@ -5005,8 +5059,12 @@ Use function list is `wl-summary-write-current-folder-functions'." (if wl-summary-buffer-disp-msg (wl-summary-redisplay)) (if interactive - (if wl-summary-buffer-next-folder-function - (funcall wl-summary-buffer-next-folder-function) + (cond + ((and (not downward) wl-summary-buffer-prev-folder-function) + (funcall wl-summary-buffer-prev-folder-function)) + ((and downward wl-summary-buffer-next-folder-function) + (funcall wl-summary-buffer-next-folder-function)) + (t (when wl-auto-select-next (setq next-entity (if downward @@ -5018,7 +5076,7 @@ Use function list is `wl-summary-write-current-folder-functions'." '(lambda () (wl-summary-next-folder-or-exit next-entity)) (format "No more messages. Type SPC to go to %s." - (wl-summary-entity-info-msg next-entity finfo)))))))) + (wl-summary-entity-info-msg next-entity finfo))))))))) (defun wl-summary-prev (&optional interactive) (interactive) @@ -5312,6 +5370,7 @@ If ASK-CODING is non-nil, coding-system for the message is asked." (defun wl-summary-supersedes-message () "Supersede current message." (interactive) + (wl-summary-toggle-disp-msg 'off) (let ((summary-buf (current-buffer)) message-buf from) (wl-summary-set-message-buffer-or-redisplay)