comparison lisp/vm/vm-summary.el @ 70:131b0175ea99 r20-0b30

Import from CVS: tag r20-0b30
author cvs
date Mon, 13 Aug 2007 09:02:59 +0200
parents 05472e90ae02
children 0d2f883870bc
comparison
equal deleted inserted replaced
69:804d1389bcd6 70:131b0175ea99
1 ;;; Summary gathering and formatting routines for VM 1 ;;; Summary gathering and formatting routines for VM
2 ;;; Copyright (C) 1989-1995 Kyle E. Jones 2 ;;; Copyright (C) 1989, 1990, 1993, 1994, 1995 Kyle E. Jones
3 ;;; 3 ;;;
4 ;;; This program is free software; you can redistribute it and/or modify 4 ;;; This program is free software; you can redistribute it and/or modify
5 ;;; it under the terms of the GNU General Public License as published by 5 ;;; it under the terms of the GNU General Public License as published by
6 ;;; the Free Software Foundation; either version 1, or (at your option) 6 ;;; the Free Software Foundation; either version 1, or (at your option)
7 ;;; any later version. 7 ;;; any later version.
20 (defun vm-summary-mode-internal () 20 (defun vm-summary-mode-internal ()
21 (setq mode-name "VM Summary" 21 (setq mode-name "VM Summary"
22 major-mode 'vm-summary-mode 22 major-mode 'vm-summary-mode
23 mode-line-format vm-mode-line-format 23 mode-line-format vm-mode-line-format
24 ;; must come after the setting of major-mode 24 ;; must come after the setting of major-mode
25 mode-popup-menu (and vm-use-menus vm-popup-menu-on-mouse-3 25 mode-popup-menu (and vm-use-menus
26 (vm-menu-support-possible-p) 26 (vm-menu-support-possible-p)
27 (vm-menu-mode-menu)) 27 (vm-menu-mode-menu))
28 buffer-read-only t 28 buffer-read-only t
29 vm-summary-pointer nil 29 vm-summary-pointer nil
30 vm-summary-=> (if (stringp vm-summary-arrow) vm-summary-arrow "") 30 vm-summary-=> (if (stringp vm-summary-arrow) vm-summary-arrow "")
31 vm-summary-no-=> (make-string (length vm-summary-=>) ? ) 31 vm-summary-no-=> (make-string (length vm-summary-=>) ? )
32 truncate-lines t) 32 truncate-lines t)
33 ;; horizontal scrollbar off by default 33 ;; horizontal scrollbar off by default
34 ;; user can turn it on in summary hook if desired. 34 ;; user can turn it on in summary hook if desired.
35 (and vm-xemacs-p (featurep 'scrollbar) 35 (and (fboundp 'set-specifier)
36 scrollbar-height
36 (set-specifier scrollbar-height (cons (current-buffer) 0))) 37 (set-specifier scrollbar-height (cons (current-buffer) 0)))
37 (use-local-map vm-summary-mode-map) 38 (use-local-map vm-summary-mode-map)
38 (and (vm-menu-support-possible-p) 39 (and (vm-menu-support-possible-p)
39 (vm-menu-install-menus)) 40 (vm-menu-install-menus))
40 (and vm-mouse-track-summary 41 (and (vm-mouse-support-possible-p)
41 (vm-mouse-support-possible-p)
42 (vm-mouse-xemacs-mouse-p) 42 (vm-mouse-xemacs-mouse-p)
43 (add-hook 'mode-motion-hook 'mode-motion-highlight-line)) 43 (add-hook 'mode-motion-hook 'mode-motion-highlight-line))
44 (if (and vm-mutable-frames (or vm-frame-per-folder vm-frame-per-summary)) 44 (if (or vm-frame-per-folder vm-frame-per-summary)
45 (vm-set-hooks-for-frame-deletion)) 45 (vm-set-hooks-for-frame-deletion))
46 (run-hooks 'vm-summary-mode-hook) 46 (run-hooks 'vm-summary-mode-hook)
47 ;; Lucid Emacs apparently used this name 47 ;; Lucid Emacs apparently used this name
48 (run-hooks 'vm-summary-mode-hooks)) 48 (run-hooks 'vm-summary-mode-hooks))
49 49
50 (fset 'vm-summary-mode 'vm-mode) 50 (fset 'vm-summary-mode 'vm-mode)
51 (put 'vm-summary-mode 'mode-class 'special) 51 (put 'vm-summary-mode 'mode-class 'special)
52 52
53 (defun vm-summarize (&optional display raise) 53 (defun vm-summarize (&optional display)
54 "Summarize the contents of the folder in a summary buffer. 54 "Summarize the contents of the folder in a summary buffer.
55 The format is as described by the variable vm-summary-format. Generally 55 The format is as described by the variable vm-summary-format. Generally
56 one line per message is most pleasing to the eye but this is not 56 one line per message is most pleasing to the eye but this is not
57 mandatory." 57 mandatory."
58 (interactive "p\np") 58 (interactive "p")
59 (vm-select-folder-buffer) 59 (vm-select-folder-buffer)
60 (vm-check-for-killed-summary) 60 (vm-check-for-killed-summary)
61 (if (null vm-summary-buffer) 61 (if (null vm-summary-buffer)
62 (let ((b (current-buffer)) 62 (let ((b (current-buffer))
63 (read-only vm-folder-read-only)) 63 (read-only vm-folder-read-only))
77 vm-folder-read-only read-only) 77 vm-folder-read-only read-only)
78 (vm-summary-mode-internal)) 78 (vm-summary-mode-internal))
79 (vm-set-summary-redo-start-point t))) 79 (vm-set-summary-redo-start-point t)))
80 (if display 80 (if display
81 (save-excursion 81 (save-excursion
82 (vm-goto-new-summary-frame-maybe) 82 (if vm-frame-per-summary
83 (let ((w (vm-get-buffer-window vm-summary-buffer)))
84 (if (null w)
85 (progn
86 (vm-goto-new-frame 'summary)
87 (vm-set-hooks-for-frame-deletion))
88 (save-excursion
89 (select-window w)
90 (and vm-warp-mouse-to-new-frame
91 (vm-warp-mouse-to-frame-maybe (vm-window-frame w)))))))
83 (vm-display vm-summary-buffer t 92 (vm-display vm-summary-buffer t
84 '(vm-summarize 93 '(vm-summarize
85 vm-summarize-other-frame) 94 vm-summarize-other-frame)
86 (list this-command) (not raise)) 95 (list this-command))
87 ;; need to do this after any frame creation because the 96 ;; need to do this after any frame creation because the
88 ;; toolbar sets frame-specific height and width specifiers. 97 ;; toolbar sets frame-specific height and width specifiers.
89 (set-buffer vm-summary-buffer) 98 (set-buffer vm-summary-buffer)
90 (and (vm-toolbar-support-possible-p) vm-use-toolbar 99 (and (vm-toolbar-support-possible-p) vm-use-toolbar
91 (vm-toolbar-install-toolbar))) 100 (vm-toolbar-install-toolbar)))
107 mp 116 mp
108 (n 0) 117 (n 0)
109 ;; Just for laughs, make the update interval vary. 118 ;; Just for laughs, make the update interval vary.
110 (modulus (+ (% (vm-abs (random)) 11) 10)) 119 (modulus (+ (% (vm-abs (random)) 11) 10))
111 (mouse-track-func 120 (mouse-track-func
112 (and vm-mouse-track-summary 121 (and (vm-mouse-support-possible-p)
113 (vm-mouse-support-possible-p)
114 (vm-mouse-fsfemacs-mouse-p) 122 (vm-mouse-fsfemacs-mouse-p)
115 (function vm-mouse-set-mouse-track-highlight))) 123 (function vm-mouse-set-mouse-track-highlight)))
116 summary) 124 summary)
117 (setq mp m-list) 125 (setq mp m-list)
118 (save-excursion 126 (save-excursion
139 (insert vm-summary-no-=>) 147 (insert vm-summary-no-=>)
140 (vm-tokenized-summary-insert (car mp) (vm-su-summary (car mp))) 148 (vm-tokenized-summary-insert (car mp) (vm-su-summary (car mp)))
141 (vm-set-su-end-of (car mp) (point)) 149 (vm-set-su-end-of (car mp) (point))
142 (setq mp (cdr mp) n (1+ n)) 150 (setq mp (cdr mp) n (1+ n))
143 (if (zerop (% n modulus)) 151 (if (zerop (% n modulus))
144 (message "Generating summary... %d" n))) 152 (vm-unsaved-message "Generating summary... %d" n)))
145 ;; now convert the ints to markers. 153 ;; now convert the ints to markers.
146 (if (>= n modulus) 154 (if (>= n modulus)
147 (message "Generating summary markers... ")) 155 (vm-unsaved-message "Generating summary markers... "))
148 (setq mp m-list) 156 (setq mp m-list)
149 (while mp 157 (while mp
150 (and mouse-track-func (funcall mouse-track-func 158 (and mouse-track-func (funcall mouse-track-func
151 (vm-su-start-of (car mp)) 159 (vm-su-start-of (car mp))
152 (vm-su-end-of (car mp)))) 160 (vm-su-end-of (car mp))))
154 (vm-set-su-end-of (car mp) (vm-marker (vm-su-end-of (car mp)))) 162 (vm-set-su-end-of (car mp) (vm-marker (vm-su-end-of (car mp))))
155 (setq mp (cdr mp)))) 163 (setq mp (cdr mp))))
156 (set-buffer-modified-p modified)) 164 (set-buffer-modified-p modified))
157 (run-hooks 'vm-summary-redo-hook))) 165 (run-hooks 'vm-summary-redo-hook)))
158 (if (>= n modulus) 166 (if (>= n modulus)
159 (message "Generating summary... done")))) 167 (vm-unsaved-message "Generating summary... done"))))
160 168
161 (defun vm-do-needed-summary-rebuild () 169 (defun vm-do-needed-summary-rebuild ()
162 (if (and vm-summary-redo-start-point vm-summary-buffer) 170 (if (and vm-summary-redo-start-point vm-summary-buffer)
163 (progn 171 (progn
164 (vm-copy-local-variables vm-summary-buffer 'vm-summary-show-threads) 172 (vm-copy-local-variables vm-summary-buffer 'vm-summary-show-threads)
178 (defun vm-update-message-summary (m) 186 (defun vm-update-message-summary (m)
179 (if (and (vm-su-start-of m) 187 (if (and (vm-su-start-of m)
180 (marker-buffer (vm-su-start-of m))) 188 (marker-buffer (vm-su-start-of m)))
181 (let ((modified (buffer-modified-p)) 189 (let ((modified (buffer-modified-p))
182 (mouse-track-func 190 (mouse-track-func
183 (and vm-mouse-track-summary 191 (and (vm-mouse-support-possible-p)
184 (vm-mouse-support-possible-p)
185 (vm-mouse-fsfemacs-mouse-p) 192 (vm-mouse-fsfemacs-mouse-p)
186 (function vm-mouse-set-mouse-track-highlight))) 193 (function vm-mouse-set-mouse-track-highlight)))
187 summary) 194 summary)
188 (save-excursion 195 (save-excursion
189 (setq summary (vm-su-summary m)) 196 (setq summary (vm-su-summary m))
194 (unwind-protect 201 (unwind-protect
195 (save-excursion 202 (save-excursion
196 (goto-char (vm-su-start-of m)) 203 (goto-char (vm-su-start-of m))
197 (setq selected (not (looking-at vm-summary-no-=>))) 204 (setq selected (not (looking-at vm-summary-no-=>)))
198 ;; We do a little dance to update the text in 205 ;; We do a little dance to update the text in
199 ;; order to make the markers in the text do 206 ;; order to make the markets in the text do
200 ;; what we want. 207 ;; what we want.
201 ;; 208 ;;
202 ;; 1. We need to avoid having the su-start-of 209 ;; 1. We need to avoid having the su-start-of
203 ;; and su-end-of markers clumping together at 210 ;; and su-end-of market clumping together at
204 ;; the start position. 211 ;; the start position.
205 ;; 212 ;;
206 ;; 2. We want the window point marker (w->pointm 213 ;; 2. We want the window point market (w->pointm
207 ;; in the Emacs display code) to move to the 214 ;; in the Emacs display code) to move to the
208 ;; start of the summary entry if it is 215 ;; start of the summary entry if it is
209 ;; anywhere within the su-start-of to 216 ;; anywhere within the su-start-of to
210 ;; su-end-of region. 217 ;; su-end-of region.
211 ;; 218 ;;
235 242
236 (defun vm-set-summary-pointer (m) 243 (defun vm-set-summary-pointer (m)
237 (if vm-summary-buffer 244 (if vm-summary-buffer
238 (let ((w (vm-get-visible-buffer-window vm-summary-buffer)) 245 (let ((w (vm-get-visible-buffer-window vm-summary-buffer))
239 (mouse-track-func 246 (mouse-track-func
240 (and vm-mouse-track-summary 247 (and (vm-mouse-support-possible-p)
241 (vm-mouse-support-possible-p)
242 (vm-mouse-fsfemacs-mouse-p) 248 (vm-mouse-fsfemacs-mouse-p)
243 (function vm-mouse-set-mouse-track-highlight))) 249 (function vm-mouse-set-mouse-track-highlight)))
244 (old-window nil)) 250 (old-window nil))
245 (vm-save-buffer-excursion 251 (vm-save-buffer-excursion
246 (unwind-protect 252 (unwind-protect
281 (and w vm-auto-center-summary (vm-auto-center-summary)) 287 (and w vm-auto-center-summary (vm-auto-center-summary))
282 (run-hooks 'vm-summary-pointer-update-hook))) 288 (run-hooks 'vm-summary-pointer-update-hook)))
283 (and old-window (select-window old-window))))))) 289 (and old-window (select-window old-window)))))))
284 290
285 (defun vm-summary-highlight-region (start end face) 291 (defun vm-summary-highlight-region (start end face)
286 (cond (vm-fsfemacs-19-p 292 (cond ((fboundp 'make-overlay)
287 (if (and vm-summary-overlay (overlay-buffer vm-summary-overlay)) 293 (if (and vm-summary-overlay (overlay-buffer vm-summary-overlay))
288 (move-overlay vm-summary-overlay start end) 294 (move-overlay vm-summary-overlay start end)
289 (setq vm-summary-overlay (make-overlay start end)) 295 (setq vm-summary-overlay (make-overlay start end))
290 (overlay-put vm-summary-overlay 'evaporate nil) 296 (overlay-put vm-summary-overlay 'evaporate nil)
291 (overlay-put vm-summary-overlay 'face face))) 297 (overlay-put vm-summary-overlay 'face face)))
292 (vm-xemacs-p 298 ((fboundp 'make-extent)
293 (if (and vm-summary-overlay (extent-end-position vm-summary-overlay)) 299 (if (and vm-summary-overlay (extent-end-position vm-summary-overlay))
294 (set-extent-endpoints vm-summary-overlay start end) 300 (set-extent-endpoints vm-summary-overlay start end)
295 (setq vm-summary-overlay (make-extent start end)) 301 (setq vm-summary-overlay (make-extent start end))
296 ;; the reason this isn't needed under FSF Emacs is
297 ;; that insert-before-markers also inserts before
298 ;; overlays! so a summary update of an entry just
299 ;; before this overlay in the summary buffer won't
300 ;; leak into the overlay, but it _will_ leak into an
301 ;; XEmacs extent.
302 (set-extent-property vm-summary-overlay 'start-open t)
303 (set-extent-property vm-summary-overlay 'detachable nil) 302 (set-extent-property vm-summary-overlay 'detachable nil)
304 (set-extent-property vm-summary-overlay 'face face))))) 303 (set-extent-property vm-summary-overlay 'face face)))))
305 304
306 (defun vm-auto-center-summary () 305 (defun vm-auto-center-summary ()
307 (if vm-auto-center-summary 306 (if vm-auto-center-summary
324 (insert tokens) 323 (insert tokens)
325 (let (token) 324 (let (token)
326 (while tokens 325 (while tokens
327 (setq token (car tokens)) 326 (setq token (car tokens))
328 (cond ((stringp token) 327 (cond ((stringp token)
329 (if vm-display-using-mime 328 (insert token))
330 (insert (vm-decode-mime-encoded-words-in-string token))
331 (insert token)))
332 ((eq token 'number) 329 ((eq token 'number)
333 (insert (vm-padded-number-of message))) 330 (insert (vm-padded-number-of message)))
334 ((eq token 'mark) 331 ((eq token 'mark)
335 (insert (vm-su-mark message))) 332 (insert (vm-su-mark message)))
336 ((eq token 'thread-indent) 333 ((eq token 'thread-indent)
443 ((= conv-spec ?*) 440 ((= conv-spec ?*)
444 (if tokenize 441 (if tokenize
445 (setq token ''mark) 442 (setq token ''mark)
446 (setq sexp (cons (list 'vm-su-mark 443 (setq sexp (cons (list 'vm-su-mark
447 'vm-su-message) sexp))))) 444 'vm-su-message) sexp)))))
448 (cond ((and (not token) vm-display-using-mime)
449 (setcar sexp
450 (list 'vm-decode-mime-encoded-words-in-string
451 (car sexp)))))
452 (cond ((and (not token) (match-beginning 1)) 445 (cond ((and (not token) (match-beginning 1))
453 (setcar sexp 446 (setcar sexp
454 (list 'vm-left-justify-string (car sexp) 447 (list 'vm-left-justify-string (car sexp)
455 (string-to-int 448 (string-to-int
456 (substring format 449 (substring format
468 (list 'vm-truncate-string (car sexp) 461 (list 'vm-truncate-string (car sexp)
469 (string-to-int 462 (string-to-int
470 (substring format 463 (substring format
471 (match-beginning 4) 464 (match-beginning 4)
472 (match-end 4))))))) 465 (match-end 4)))))))
473 (cond ((and (not token) vm-display-using-mime)
474 (setcar sexp
475 (list 'vm-reencode-mime-encoded-words-in-string
476 (car sexp)))))
477 (setq sexp-fmt 466 (setq sexp-fmt
478 (cons (if token "" "%s") 467 (cons (if token "" "%s")
479 (cons (substring format 468 (cons (substring format
480 last-match-end 469 last-match-end
481 (match-beginning 0)) 470 (match-beginning 0))
502 sexp nil 491 sexp nil
503 sexp-fmt nil))) 492 sexp-fmt nil)))
504 (put format-variable 'vm-compiled-format format) 493 (put format-variable 'vm-compiled-format format)
505 (put format-variable 'vm-format-sexp (if list (cons 'list list) sexp)))) 494 (put format-variable 'vm-format-sexp (if list (cons 'list list) sexp))))
506 495
507 (defun vm-get-header-contents (message header-name-regexp &optional clump-sep) 496 (defun vm-get-header-contents (message header-name-regexp)
508 (let ((contents nil) 497 (let ((contents nil)
509 regexp) 498 regexp)
510 (setq regexp (concat "^\\(" header-name-regexp "\\)") 499 (setq regexp (concat "^\\(" header-name-regexp "\\)")
511 message (vm-real-message-of message)) 500 message (vm-real-message-of message))
512 (save-excursion 501 (save-excursion
513 (set-buffer (vm-buffer-of (vm-real-message-of message))) 502 (set-buffer (vm-buffer-of (vm-real-message-of message)))
514 (save-restriction 503 (save-restriction
515 (widen) 504 (widen)
516 (goto-char (vm-headers-of message)) 505 (goto-char (vm-headers-of message))
517 (let ((case-fold-search t)) 506 (let ((case-fold-search t))
518 (while (and (or (null contents) clump-sep) 507 (while (and (re-search-forward regexp (vm-text-of message) t)
519 (re-search-forward regexp (vm-text-of message) t)
520 (save-excursion (goto-char (match-beginning 0)) 508 (save-excursion (goto-char (match-beginning 0))
521 (vm-match-header))) 509 (vm-match-header)))
522 (if contents 510 (if contents
523 (setq contents 511 (setq contents
524 (concat contents clump-sep (vm-matched-header-contents))) 512 (concat contents ", " (vm-matched-header-contents)))
525 (setq contents (vm-matched-header-contents)))))) 513 (setq contents (vm-matched-header-contents))))))
526 contents ))) 514 contents )))
527 515
528 (defun vm-left-justify-string (string width) 516 (defun vm-left-justify-string (string width)
529 (if (>= (length string) width) 517 (if (>= (length string) width)
534 (if (>= (length string) width) 522 (if (>= (length string) width)
535 string 523 string
536 (concat (make-string (- width (length string)) ?\ ) string))) 524 (concat (make-string (- width (length string)) ?\ ) string)))
537 525
538 (defun vm-truncate-string (string width) 526 (defun vm-truncate-string (string width)
539 (cond 527 (cond ((<= (length string) width)
540 ;; doesn't work because the width of wide chars such as the Kanji
541 ;; glyphs as not even multiples of the default face's font width.
542 ;; ((fboundp 'char-width)
543 ;; (let ((i 0)
544 ;; (lim (length string))
545 ;; (total 0))
546 ;; (while (and (< i lim) (<= total width))
547 ;; (setq total (+ total (char-width (aref string i)))
548 ;; i (1+ i)))
549 ;; (if (<= total width)
550 ;; string
551 ;; (substring string 0 (1- i)))))
552 ((<= (length string) width)
553 string) 528 string)
554 ((< width 0) 529 ((< width 0)
555 (substring string width)) 530 (substring string width))
556 (t 531 (t
557 (substring string 0 width)))) 532 (substring string 0 width))))
635 (if (not (memq (vm-message-type-of message) 610 (if (not (memq (vm-message-type-of message)
636 '(From_ From_-with-Content-Length))) 611 '(From_ From_-with-Content-Length)))
637 nil 612 nil
638 (save-excursion 613 (save-excursion
639 (set-buffer (vm-buffer-of (vm-real-message-of message))) 614 (set-buffer (vm-buffer-of (vm-real-message-of message)))
640 (save-excursion 615 (save-restriction
641 (save-restriction 616 (widen)
642 (widen) 617 (goto-char (vm-start-of message))
643 (goto-char (vm-start-of message)) 618 (let ((case-fold-search nil))
644 (let ((case-fold-search nil)) 619 (if (or (looking-at
645 (if (or (looking-at 620 ;; special case this so that the "remote from blah"
646 ;; special case this so that the "remote from blah" 621 ;; isn't included.
647 ;; isn't included. 622 "From [^ \t\n]*[ \t]+\\([^ \t\n].*\\) remote from .*")
648 "From [^ \t\n]*[ \t]+\\([^ \t\n].*\\) remote from .*") 623 (looking-at "From [^ \t\n]*[ \t]+\\([^ \t\n].*\\)"))
649 (looking-at "From [^ \t\n]*[ \t]+\\([^ \t\n].*\\)")) 624 (vm-buffer-substring-no-properties
650 (vm-buffer-substring-no-properties 625 (match-beginning 1)
651 (match-beginning 1) 626 (match-end 1))))))))
652 (match-end 1)))))))))
653 627
654 (defun vm-parse-date (date) 628 (defun vm-parse-date (date)
655 (let ((weekday "") 629 (let ((weekday "")
656 (monthday "") 630 (monthday "")
657 (month "") 631 (month "")
732 (vm-set-monthday-of m (substring date (match-beginning 3) (match-end 3))) 706 (vm-set-monthday-of m (substring date (match-beginning 3) (match-end 3)))
733 (vm-set-hour-of m (substring date (match-beginning 4) (match-end 4))) 707 (vm-set-hour-of m (substring date (match-beginning 4) (match-end 4)))
734 (vm-set-year-of m (substring date (match-beginning 5) (match-end 5))) 708 (vm-set-year-of m (substring date (match-beginning 5) (match-end 5)))
735 (if (match-beginning 6) 709 (if (match-beginning 6)
736 (vm-set-zone-of m (substring date (match-beginning 6) 710 (vm-set-zone-of m (substring date (match-beginning 6)
737 (match-end 6))) 711 (match-end 6)))))
738 (vm-set-zone-of m "")))
739 (t 712 (t
740 (setq vector (vm-parse-date date)) 713 (setq vector (vm-parse-date date))
741 (vm-set-weekday-of m (elt vector 0)) 714 (vm-set-weekday-of m (elt vector 0))
742 (vm-set-monthday-of m (elt vector 1)) 715 (vm-set-monthday-of m (elt vector 1))
743 (vm-su-do-month m (elt vector 2)) 716 (vm-su-do-month m (elt vector 2))
804 (if (not (memq (vm-message-type-of message) 777 (if (not (memq (vm-message-type-of message)
805 '(From_ From_-with-Content-Length))) 778 '(From_ From_-with-Content-Length)))
806 nil 779 nil
807 (save-excursion 780 (save-excursion
808 (set-buffer (vm-buffer-of message)) 781 (set-buffer (vm-buffer-of message))
809 (save-excursion 782 (save-restriction
810 (save-restriction 783 (widen)
811 (widen) 784 (goto-char (vm-start-of message))
812 (goto-char (vm-start-of message)) 785 (let ((case-fold-search nil))
813 (let ((case-fold-search nil)) 786 (if (looking-at "From \\([^ \t\n]+\\)")
814 (if (looking-at "From \\([^ \t\n]+\\)") 787 (vm-buffer-substring-no-properties
815 (vm-buffer-substring-no-properties 788 (match-beginning 1)
816 (match-beginning 1) 789 (match-end 1))))))))
817 (match-end 1)))))))))
818 790
819 (defun vm-su-do-author (m) 791 (defun vm-su-do-author (m)
820 (let ((full-name (vm-get-header-contents m "Full-Name:")) 792 (let ((full-name (vm-get-header-contents m "Full-Name:"))
821 (from (or (vm-get-header-contents m "From:" ", ") 793 (from (or (vm-get-header-contents m "From:")
822 (vm-grok-From_-author m))) 794 (vm-grok-From_-author m)))
823 pair i) 795 pair)
824 (if (and full-name (string-match "^[ \t]*$" full-name)) 796 (if (and full-name (string-match "^[ \t]*$" full-name))
825 (setq full-name nil)) 797 (setq full-name nil))
826 (if (null from) 798 (if (null from)
827 (progn 799 (progn
828 (setq from "???") 800 (setq from "???")
832 from (or (nth 1 pair) from) 804 from (or (nth 1 pair) from)
833 full-name (or full-name (nth 0 pair) from))) 805 full-name (or full-name (nth 0 pair) from)))
834 (if (string-match "\\`\"\\([^\"]+\\)\"\\'" full-name) 806 (if (string-match "\\`\"\\([^\"]+\\)\"\\'" full-name)
835 (setq full-name 807 (setq full-name
836 (substring full-name (match-beginning 1) (match-end 1)))) 808 (substring full-name (match-beginning 1) (match-end 1))))
837 (while (setq i (string-match "\n" full-name i))
838 (aset full-name i ?\ ))
839 (vm-set-full-name-of m full-name) 809 (vm-set-full-name-of m full-name)
840 (vm-set-from-of m from))) 810 (vm-set-from-of m from)))
841 811
842 (defun vm-default-chop-full-name (address) 812 (defun vm-default-chop-full-name (address)
843 (let ((from address) 813 (let ((from address)
890 ;; it passed the tests 860 ;; it passed the tests
891 (setq vm-chop-full-name-function 'mail-extract-address-components)) 861 (setq vm-chop-full-name-function 'mail-extract-address-components))
892 (funcall vm-chop-full-name-function address))) 862 (funcall vm-chop-full-name-function address)))
893 863
894 (defun vm-su-do-recipients (m) 864 (defun vm-su-do-recipients (m)
895 (let ((mail-use-rfc822 t) i names addresses to cc all list full-name) 865 (let ((mail-use-rfc822 t) names addresses to cc all list)
896 (setq to (or (vm-get-header-contents m "To:" ", ") 866 (setq to (or (vm-get-header-contents m "To:")
897 (vm-get-header-contents m "Apparently-To:" ", ") 867 (vm-get-header-contents m "Apparently-To:")
898 ;; desperation.... 868 ;; desperation....
899 (user-login-name)) 869 (user-login-name))
900 cc (vm-get-header-contents m "Cc:" ", ") 870 cc (vm-get-header-contents m "Cc:")
901 all to 871 all to
902 all (if all (concat all ", " cc) cc) 872 all (if all (concat all ", " cc) cc)
903 addresses (rfc822-addresses all)) 873 addresses (rfc822-addresses all))
904 (setq list (vm-parse-addresses all)) 874 (setq list (vm-parse-addresses all))
905 (while list 875 (while list
906 ;; Just like vm-su-do-author: 876 (cond ((string= (car list) ""))
907 (setq full-name (or (nth 0 (funcall vm-chop-full-name-function 877 ((string-match "^\\(\"?\\([^<]+[^ \t\n\"]\\)\"?[ \t\n]+\\)?<\\([^>]+\\)>"
908 (car list))) 878 (car list))
909 (car list))) 879 (if (match-beginning 2)
910 ;; If double quoted are around the full name, fish the name out. 880 (setq names
911 (if (string-match "\\`\"\\([^\"]+\\)\"\\'" full-name) 881 (cons
912 (setq full-name 882 (substring (car list) (match-beginning 2)
913 (substring full-name (match-beginning 1) (match-end 1)))) 883 (match-end 2))
914 (while (setq i (string-match "\n" full-name i)) 884 names))
915 (aset full-name i ?\ )) 885 (setq names
916 (setq names (cons full-name names)) 886 (cons
887 (substring (car list) (match-beginning 3)
888 (match-end 3))
889 names))))
890 ((string-match "[\000-\177]*(\\([^)]+\\))[\000-\177]*" (car list))
891 (setq names
892 (cons (substring (car list) (match-beginning 1)
893 (match-end 1))
894 names)))
895 (t (setq names (cons (car list) names))))
917 (setq list (cdr list))) 896 (setq list (cdr list)))
918 (setq names (nreverse names)) ; added by jwz for fixed vm-parse-addresses 897 (setq names (nreverse names)) ; added by jwz for fixed vm-parse-addresses
919 (vm-set-to-of m (mapconcat 'identity addresses ", ")) 898 (vm-set-to-of m (mapconcat 'identity addresses ", "))
920 (vm-set-to-names-of m (mapconcat 'identity names ", ")))) 899 (vm-set-to-names-of m (mapconcat 'identity names ", "))))
921 900
927 906
928 (defun vm-su-message-id (m) 907 (defun vm-su-message-id (m)
929 (or (vm-message-id-of m) 908 (or (vm-message-id-of m)
930 (vm-set-message-id-of 909 (vm-set-message-id-of
931 m 910 m
932 (or (let ((id (vm-get-header-contents m "Message-Id:"))) 911 (or (vm-get-header-contents m "Message-Id:")
933 (and id (car (vm-parse id "[^<]*\\(<[^>]+>\\)"))))
934 ;; try running md5 on the message body to produce an ID 912 ;; try running md5 on the message body to produce an ID
935 ;; better than nothing. 913 ;; better than nothing.
936 (save-excursion 914 (save-excursion
937 (set-buffer (vm-buffer-of (vm-real-message-of m))) 915 (set-buffer (vm-buffer-of (vm-real-message-of m)))
938 (save-restriction 916 (save-restriction
961 939
962 (defun vm-su-subject (m) 940 (defun vm-su-subject (m)
963 (or (vm-subject-of m) 941 (or (vm-subject-of m)
964 (vm-set-subject-of 942 (vm-set-subject-of
965 m 943 m
966 (let ((subject (or (vm-get-header-contents m "Subject:" " ") "")) 944 (let ((subject (or (vm-get-header-contents m "Subject:") ""))
967 (i nil)) 945 (i nil))
968 (while (setq i (string-match "\n" subject i)) 946 (if vm-summary-subject-no-newlines
969 (aset subject i ?\ )) 947 (while (setq i (string-match "\n" subject i))
948 (aset subject i ?\ )))
970 subject )))) 949 subject ))))
971 950
972 (defun vm-su-summary (m) 951 (defun vm-su-summary (m)
973 (if (and (vm-virtual-message-p m) (not (vm-virtual-messages-of m))) 952 (if (and (vm-virtual-message-p m) (not (vm-virtual-messages-of m)))
974 (or (vm-virtual-summary-of m) 953 (or (vm-virtual-summary-of m)
985 (defun vm-fix-my-summary!!! () 964 (defun vm-fix-my-summary!!! ()
986 (interactive) 965 (interactive)
987 (vm-select-folder-buffer) 966 (vm-select-folder-buffer)
988 (vm-check-for-killed-summary) 967 (vm-check-for-killed-summary)
989 (vm-error-if-folder-empty) 968 (vm-error-if-folder-empty)
990 (message "Fixing your summary...") 969 (vm-unsaved-message "Fixing your summary...")
991 (let ((mp vm-message-list)) 970 (let ((mp vm-message-list))
992 (while mp 971 (while mp
993 (vm-set-summary-of (car mp) nil) 972 (vm-set-summary-of (car mp) nil)
994 (vm-mark-for-summary-update (car mp)) 973 (vm-mark-for-summary-update (car mp))
974 (vm-stuff-attributes (car mp))
995 (setq mp (cdr mp))) 975 (setq mp (cdr mp)))
996 (vm-stuff-folder-attributes nil)
997 (set-buffer-modified-p t) 976 (set-buffer-modified-p t)
998 (vm-update-summary-and-mode-line)) 977 (vm-update-summary-and-mode-line))
999 (message "Fixing your summary... done")) 978 (vm-unsaved-message "Fixing your summary... done"))
1000 979
1001 (defun vm-su-thread-indent (m) 980 (defun vm-su-thread-indent (m)
1002 (if (natnump vm-summary-thread-indent-level) 981 (if (natnump vm-summary-thread-indent-level)
1003 (make-string (* (vm-th-thread-indentation m) 982 (make-string (* (vm-th-thread-indentation m)
1004 vm-summary-thread-indent-level) 983 vm-summary-thread-indent-level)