aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman2009-01-05 15:49:50 +0000
committerRichard M. Stallman2009-01-05 15:49:50 +0000
commitf79e69b91f9d621e22e63ad88381f2af63cd48f5 (patch)
tree22c8a12fb3cf8c3fe17b835e91d0f0f9dbaaca35
parent4e756c2469a097ca1edffc6bbe9caac16447c4c3 (diff)
downloademacs-f79e69b91f9d621e22e63ad88381f2af63cd48f5.tar.gz
emacs-f79e69b91f9d621e22e63ad88381f2af63cd48f5.zip
(basic-save-buffer): Protect buffer-modified flag around first swap.
(pmail-show-message): Protect buffer-modified flag around swap. (pmail-change-major-mode-hook): Likewise. (pmail-use-collection-buffer, pmail-swap-buffers-maybe): Likewise. (pmail-error-bad-format): Always phrase the error as about an invalid message. (pmail-convert-file-maybe): Don't use pmail-error-bad-format. (pmail-mode-map): Move pmail-widen to C-c C-w. (pmail-mode-1): Don't alter mode-line-modified. (pmail-perm-variables): Turn off undo in view buffer. (pmail-variables): Turn off undo. (pmail-show-message): Delete useless calls to `widen'. Avoid passing thru temp buffer if we don't need base64 or quoted printable decoding for whole message. (pmail-keywords): Variable deleted. (pmail-last-label, pmail-last-multi-labels): Moved to pmailkwd.el. (pmail-perm-variables): Don't mess with pmail-last-label. Don't mess with pmail-keywords. (pmail-copy-headers): Doc fix. (pmail-set-header): New function. (pmail-get-keywords): Doc fix. (pmail-get-labels): New function. (pmail-display-labels): Use pmail-get-labels. (pmail-set-attribute): Mark pmail-buffer modified if we change an attribute. (pmail-apply-in-message): New function. (pmail-message-labels-p): Function moved to pmailsum.el. (pmail-message-recipients-p, pmail-message-regexp-p): Likewise. (pmail-current-subject, pmail-current-subject-regexp): Fns deleted. (pmail-simplified-subject, pmail-simplified-subject-regexp): New fns. (pmail-next-same-subject): Fetch each msg's subject and compare. (pmail-speedbar-move-message): Use pmail-output. (pmail-construct-io-menu): Use pmail-output. (pmail-default-pmail-file): Variable deleted. (pmail-auto-file): Use pmail-output. (pmail-mode-map): Remove pmail-output-to-babyl-file. Add pmail-output-as-seen. (pmail-mode): Update output commands in doc string.
-rw-r--r--lisp/mail/pmail.el343
1 files changed, 173 insertions, 170 deletions
diff --git a/lisp/mail/pmail.el b/lisp/mail/pmail.el
index 5d9dc9d50c2..6f351344398 100644
--- a/lisp/mail/pmail.el
+++ b/lisp/mail/pmail.el
@@ -60,9 +60,18 @@ temporarily unswap in order to save the real contents. This
60advice is temporarily used by pmail until a satisfactory solution 60advice is temporarily used by pmail until a satisfactory solution
61can be written." 61can be written."
62 (if (not buffer-swapped-with) 62 (if (not buffer-swapped-with)
63 ad-do-it 63 (progn
64;; (if (and (string= "PMAIL" (buffer-name))
65;; (< (buffer-size) 1000000))
66;; (debug))
67 ad-do-it)
64 (unwind-protect 68 (unwind-protect
65 (let ((modp (buffer-modified-p))) 69 (let ((modp (buffer-modified-p)))
70;; (save-match-data
71;; (let ((case-fold-search nil))
72;; (unless (or (string-match "PMAIL" (buffer-name))
73;; (string-match "xmail" (buffer-name)))
74;; (debug))))
66 (buffer-swap-text buffer-swapped-with) 75 (buffer-swap-text buffer-swapped-with)
67 (set-buffer-modified-p modp) 76 (set-buffer-modified-p modp)
68 ad-do-it) 77 ad-do-it)
@@ -567,9 +576,6 @@ examples:
567(defvar pmail-inbox-list nil) 576(defvar pmail-inbox-list nil)
568(put 'pmail-inbox-list 'permanent-local t) 577(put 'pmail-inbox-list 'permanent-local t)
569 578
570(defvar pmail-keywords nil)
571(put 'pmail-keywords 'permanent-local t)
572
573(defvar pmail-buffer nil 579(defvar pmail-buffer nil
574 "The PMAIL buffer related to the current buffer. 580 "The PMAIL buffer related to the current buffer.
575In an PMAIL buffer, this holds the PMAIL buffer itself. 581In an PMAIL buffer, this holds the PMAIL buffer itself.
@@ -612,13 +618,6 @@ by substituting the new message number into the existing list.")
612 618
613;; `Sticky' default variables. 619;; `Sticky' default variables.
614 620
615;; Last individual label specified to a or k.
616(defvar pmail-last-label nil)
617(put 'pmail-last-label 'permanent-local t)
618
619;; Last set of values specified to C-M-n, C-M-p, C-M-s or C-M-l.
620(defvar pmail-last-multi-labels nil)
621
622(defvar pmail-last-regexp nil) 621(defvar pmail-last-regexp nil)
623(put 'pmail-last-regexp 'permanent-local t) 622(put 'pmail-last-regexp 'permanent-local t)
624 623
@@ -626,10 +625,6 @@ by substituting the new message number into the existing list.")
626 "*Default file name for \\[pmail-output]." 625 "*Default file name for \\[pmail-output]."
627 :type 'file 626 :type 'file
628 :group 'pmail-files) 627 :group 'pmail-files)
629(defcustom pmail-default-pmail-file "~/XMAIL"
630 "*Default file name for \\[pmail-output-to-babyl-file]."
631 :type 'file
632 :group 'pmail-files)
633(defcustom pmail-default-body-file "~/mailout" 628(defcustom pmail-default-body-file "~/mailout"
634 "*Default file name for \\[pmail-output-body-to-file]." 629 "*Default file name for \\[pmail-output-body-to-file]."
635 :type 'file 630 :type 'file
@@ -946,14 +941,14 @@ If `pmail-display-summary' is non-nil, make a summary for this PMAIL file."
946 ((equal (point-min) (point-max)) 941 ((equal (point-min) (point-max))
947 (message "Empty Pmail file.")) 942 (message "Empty Pmail file."))
948 ((looking-at "From ")) 943 ((looking-at "From "))
949 (t (pmail-error-bad-format)))) 944 (t (error "Invalid mbox file"))))
950 945
951(defun pmail-error-bad-format (&optional msgnum) 946(defun pmail-error-bad-format (&optional msgnum)
952 "Report that the buffer is not in the mbox file format. 947 "Report that the buffer is not in the mbox file format.
953MSGNUM, if present, indicates the malformed message." 948MSGNUM, if present, indicates the malformed message."
954 (if msgnum 949 (if msgnum
955 (error "Message %s is not a valid RFC2822 message." msgnum) 950 (error "Message %d is not a valid RFC2822 message" msgnum)
956 (error "Invalid mbox format mail file."))) 951 (error "Message is not a valid RFC2822 message")))
957 952
958(defun pmail-convert-babyl-to-mbox () 953(defun pmail-convert-babyl-to-mbox ()
959 "Convert the mail file from Babyl version 5 to mbox. 954 "Convert the mail file from Babyl version 5 to mbox.
@@ -989,6 +984,8 @@ The buffer is expected to be narrowed to just the header of the message."
989 (string-match pmail-mime-charset-pattern content-type-header)) 984 (string-match pmail-mime-charset-pattern content-type-header))
990 (substring content-type-header (match-beginning 1) (match-end 1)) 985 (substring content-type-header (match-beginning 1) (match-end 1))
991 'undecided))) 986 'undecided)))
987
988;;; Set up Pmail mode keymaps
992 989
993(defvar pmail-mode-map nil) 990(defvar pmail-mode-map nil)
994(if pmail-mode-map 991(if pmail-mode-map
@@ -1032,7 +1029,7 @@ The buffer is expected to be narrowed to just the header of the message."
1032 (define-key pmail-mode-map "t" 'pmail-toggle-header) 1029 (define-key pmail-mode-map "t" 'pmail-toggle-header)
1033 (define-key pmail-mode-map "u" 'pmail-undelete-previous-message) 1030 (define-key pmail-mode-map "u" 'pmail-undelete-previous-message)
1034 (define-key pmail-mode-map "w" 'pmail-output-body-to-file) 1031 (define-key pmail-mode-map "w" 'pmail-output-body-to-file)
1035 (define-key pmail-mode-map "C-w" 'pmail-widen) 1032 (define-key pmail-mode-map "\C-c\C-w" 'pmail-widen)
1036 (define-key pmail-mode-map "x" 'pmail-expunge) 1033 (define-key pmail-mode-map "x" 'pmail-expunge)
1037 (define-key pmail-mode-map "." 'pmail-beginning-of-message) 1034 (define-key pmail-mode-map "." 'pmail-beginning-of-message)
1038 (define-key pmail-mode-map "/" 'pmail-end-of-message) 1035 (define-key pmail-mode-map "/" 'pmail-end-of-message)
@@ -1067,10 +1064,10 @@ The buffer is expected to be narrowed to just the header of the message."
1067 '("Output body to file..." . pmail-output-body-to-file)) 1064 '("Output body to file..." . pmail-output-body-to-file))
1068 1065
1069(define-key pmail-mode-map [menu-bar classify output-inbox] 1066(define-key pmail-mode-map [menu-bar classify output-inbox]
1070 '("Output (inbox)..." . pmail-output)) 1067 '("Output..." . pmail-output))
1071 1068
1072(define-key pmail-mode-map [menu-bar classify output] 1069(define-key pmail-mode-map [menu-bar classify output]
1073 '("Output (Pmail)..." . pmail-output-to-babyl-file)) 1070 '("Output as seen..." . pmail-output-as-seen))
1074 1071
1075(define-key pmail-mode-map [menu-bar classify kill-label] 1072(define-key pmail-mode-map [menu-bar classify kill-label]
1076 '("Kill Label..." . pmail-kill-label)) 1073 '("Kill Label..." . pmail-kill-label))
@@ -1238,8 +1235,8 @@ Instead, these commands are available:
1238\\[pmail-reply] Reply to this message. Like \\[pmail-mail] but initializes some fields. 1235\\[pmail-reply] Reply to this message. Like \\[pmail-mail] but initializes some fields.
1239\\[pmail-retry-failure] Send this message again. Used on a mailer failure message. 1236\\[pmail-retry-failure] Send this message again. Used on a mailer failure message.
1240\\[pmail-forward] Forward this message to another user. 1237\\[pmail-forward] Forward this message to another user.
1241\\[pmail-output-to-babyl-file] Output this message to an Pmail file (append it). 1238\\[pmail-output] Output (append) this message to another mail file.
1242\\[pmail-output] Output this message to a Unix-format mail file (append it). 1239\\[pmail-output-as-seen] Output (append) this message to file as it's displayed.
1243\\[pmail-output-body-to-file] Save message body to a file. Default filename comes from Subject line. 1240\\[pmail-output-body-to-file] Save message body to a file. Default filename comes from Subject line.
1244\\[pmail-input] Input Pmail file. Run Pmail on that file. 1241\\[pmail-input] Input Pmail file. Run Pmail on that file.
1245\\[pmail-add-label] Add label to message. It will be displayed in the mode line. 1242\\[pmail-add-label] Add label to message. It will be displayed in the mode line.
@@ -1287,10 +1284,9 @@ Instead, these commands are available:
1287 ;; No need to auto save PMAIL files in normal circumstances 1284 ;; No need to auto save PMAIL files in normal circumstances
1288 ;; because they contain no info except attribute changes 1285 ;; because they contain no info except attribute changes
1289 ;; and deletion of messages. 1286 ;; and deletion of messages.
1290 ;; The one exception is when messages are copied into an Pmail mode buffer. 1287 ;; The one exception is when messages are copied into another mbox buffer.
1291 ;; pmail-output-to-babyl-file enables auto save when you do that. 1288 ;; pmail-output enables auto save when you do that.
1292 (setq buffer-auto-save-file-name nil) 1289 (setq buffer-auto-save-file-name nil)
1293 (setq mode-line-modified "--")
1294 (use-local-map pmail-mode-map) 1290 (use-local-map pmail-mode-map)
1295 (set-syntax-table text-mode-syntax-table) 1291 (set-syntax-table text-mode-syntax-table)
1296 (setq local-abbrev-table text-mode-abbrev-table) 1292 (setq local-abbrev-table text-mode-abbrev-table)
@@ -1312,7 +1308,9 @@ Create the buffer if necessary."
1312 (if buffer-swapped-with 1308 (if buffer-swapped-with
1313 (when (pmail-buffers-swapped-p) 1309 (when (pmail-buffers-swapped-p)
1314 (setq buffer-swapped-with nil) 1310 (setq buffer-swapped-with nil)
1315 (buffer-swap-text pmail-view-buffer)))) 1311 (let ((modp (buffer-modified-p)))
1312 (buffer-swap-text pmail-view-buffer)
1313 (set-buffer-modified-p modp)))))
1316 ;; Throw away the summary. 1314 ;; Throw away the summary.
1317 ;;(when (buffer-live-p pmail-view-buffer) (kill-buffer pmail-view-buffer))) 1315 ;;(when (buffer-live-p pmail-view-buffer) (kill-buffer pmail-view-buffer)))
1318 1316
@@ -1330,7 +1328,6 @@ Create the buffer if necessary."
1330 1328
1331;; Set up the permanent locals associated with an Pmail file. 1329;; Set up the permanent locals associated with an Pmail file.
1332(defun pmail-perm-variables () 1330(defun pmail-perm-variables ()
1333 (make-local-variable 'pmail-last-label)
1334 (make-local-variable 'pmail-last-regexp) 1331 (make-local-variable 'pmail-last-regexp)
1335 (make-local-variable 'pmail-deleted-vector) 1332 (make-local-variable 'pmail-deleted-vector)
1336 (make-local-variable 'pmail-buffer) 1333 (make-local-variable 'pmail-buffer)
@@ -1340,6 +1337,7 @@ Create the buffer if necessary."
1340 (save-excursion 1337 (save-excursion
1341 (setq pmail-view-buffer (pmail-generate-viewer-buffer)) 1338 (setq pmail-view-buffer (pmail-generate-viewer-buffer))
1342 (set-buffer pmail-view-buffer) 1339 (set-buffer pmail-view-buffer)
1340 (setq buffer-undo-list t)
1343 (set-buffer-multibyte t)) 1341 (set-buffer-multibyte t))
1344 (make-local-variable 'pmail-summary-buffer) 1342 (make-local-variable 'pmail-summary-buffer)
1345 (make-local-variable 'pmail-summary-vector) 1343 (make-local-variable 'pmail-summary-vector)
@@ -1361,13 +1359,12 @@ Create the buffer if necessary."
1361 (list (or (getenv "MAIL") 1359 (list (or (getenv "MAIL")
1362 (concat rmail-spool-directory 1360 (concat rmail-spool-directory
1363 (user-login-name))))))) 1361 (user-login-name)))))))
1364 (make-local-variable 'pmail-keywords) 1362 (set (make-local-variable 'tool-bar-map) pmail-tool-bar-map))
1365 (set (make-local-variable 'tool-bar-map) pmail-tool-bar-map)
1366 ;; this gets generated as needed
1367 (setq pmail-keywords nil))
1368 1363
1369;; Set up the non-permanent locals associated with Pmail mode. 1364;; Set up the non-permanent locals associated with Pmail mode.
1370(defun pmail-variables () 1365(defun pmail-variables ()
1366 ;; Turn off undo. We turn it back on in pmail-edit.
1367 (setq buffer-undo-list t)
1371 ;; Don't let a local variables list in a message cause confusion. 1368 ;; Don't let a local variables list in a message cause confusion.
1372 (make-local-variable 'local-enable-local-variables) 1369 (make-local-variable 'local-enable-local-variables)
1373 (setq local-enable-local-variables nil) 1370 (setq local-enable-local-variables nil)
@@ -1391,7 +1388,7 @@ Create the buffer if necessary."
1391 (setq file-precious-flag t) 1388 (setq file-precious-flag t)
1392 (make-local-variable 'desktop-save-buffer) 1389 (make-local-variable 'desktop-save-buffer)
1393 (setq desktop-save-buffer t)) 1390 (setq desktop-save-buffer t))
1394 1391
1395;; Handle M-x revert-buffer done in an pmail-mode buffer. 1392;; Handle M-x revert-buffer done in an pmail-mode buffer.
1396(defun pmail-revert (arg noconfirm) 1393(defun pmail-revert (arg noconfirm)
1397 (set-buffer pmail-buffer) 1394 (set-buffer pmail-buffer)
@@ -1466,7 +1463,7 @@ Hook `pmail-quit-hook' is run after expunging."
1466 (quit-window nil window)) 1463 (quit-window nil window))
1467 (bury-buffer pmail-summary-buffer))) 1464 (bury-buffer pmail-summary-buffer)))
1468 (quit-window))) 1465 (quit-window)))
1469 1466
1470(defun pmail-duplicate-message () 1467(defun pmail-duplicate-message ()
1471 "Create a duplicated copy of the current message. 1468 "Create a duplicated copy of the current message.
1472The duplicate copy goes into the Pmail file just after the 1469The duplicate copy goes into the Pmail file just after the
@@ -1547,7 +1544,7 @@ original copy."
1547 (cons "Output Pmail File" 1544 (cons "Output Pmail File"
1548 (pmail-list-to-menu "Output Pmail File" 1545 (pmail-list-to-menu "Output Pmail File"
1549 files 1546 files
1550 'pmail-output-to-babyl-file)))) 1547 'pmail-output))))
1551 1548
1552 (define-key pmail-mode-map [menu-bar classify input-menu] 1549 (define-key pmail-mode-map [menu-bar classify input-menu]
1553 '("Input Pmail File" . pmail-disable-menu)) 1550 '("Input Pmail File" . pmail-disable-menu))
@@ -1993,7 +1990,7 @@ new messages. Return the number of new messages."
1993(defun pmail-copy-headers (beg end &optional ignored-headers) 1990(defun pmail-copy-headers (beg end &optional ignored-headers)
1994 "Copy displayed header fields to the message viewer buffer. 1991 "Copy displayed header fields to the message viewer buffer.
1995BEG and END marks the start and end positions of the message in 1992BEG and END marks the start and end positions of the message in
1996the mail buffer. If the optional argument IGNORED-HEADERS is 1993the mbox buffer. If the optional argument IGNORED-HEADERS is
1997non-nil, ignore all header fields whose names match that regexp. 1994non-nil, ignore all header fields whose names match that regexp.
1998Otherwise, if `rmail-displayed-headers' is non-nil, copy only 1995Otherwise, if `rmail-displayed-headers' is non-nil, copy only
1999those header fields whose names match that regexp. Otherwise, 1996those header fields whose names match that regexp. Otherwise,
@@ -2062,8 +2059,6 @@ otherwise, show it in full."
2062 (goto-char (point-min)) 2059 (goto-char (point-min))
2063 (vertical-motion (- (point-max) (point-min)))))) 2060 (vertical-motion (- (point-max) (point-min))))))
2064 2061
2065;;;; *** Pmail Attributes and Keywords ***
2066
2067(defun pmail-get-header (name &optional msgnum) 2062(defun pmail-get-header (name &optional msgnum)
2068 "Return the value of message header NAME, nil if it has none. 2063 "Return the value of message header NAME, nil if it has none.
2069MSGNUM specifies the message number to get it from. 2064MSGNUM specifies the message number to get it from.
@@ -2088,6 +2083,41 @@ If MSGNUM is nil, use the current message."
2088 (mail-fetch-field name)) 2083 (mail-fetch-field name))
2089 (pmail-error-bad-format msgnum))))))))) 2084 (pmail-error-bad-format msgnum)))))))))
2090 2085
2086(defun pmail-set-header (name &optional msgnum value)
2087 "Store VALUE in message header NAME, nil if it has none.
2088MSGNUM specifies the message number to operate on.
2089If MSGNUM is nil, use the current message."
2090 (with-current-buffer pmail-buffer
2091 (or msgnum (setq msgnum pmail-current-message))
2092 (when (> msgnum 0)
2093 (let (msgbeg end)
2094 (setq msgbeg (pmail-msgbeg msgnum))
2095 ;; All access to the buffer's local variables is now finished...
2096 (save-excursion
2097 ;; ... so it is ok to go to a different buffer.
2098 (if (pmail-buffers-swapped-p) (set-buffer pmail-view-buffer))
2099 (save-restriction
2100 (widen)
2101 (save-excursion
2102 (goto-char msgbeg)
2103 (setq end (search-forward "\n\n" nil t))
2104 (if end (setq end (1- end)))
2105 (if end
2106 (progn
2107 (narrow-to-region msgbeg end)
2108 (goto-char msgbeg)
2109 (if (re-search-forward (concat "^"
2110 (regexp-quote name)
2111 ":")
2112 nil t)
2113 (progn
2114 (delete-region (point) (line-end-position))
2115 (insert " " value))
2116 (goto-char end)
2117 (insert name ": " value "\n")))
2118 (pmail-error-bad-format msgnum)))))))))
2119
2120;;;; *** Pmail Attributes and Keywords ***
2091 2121
2092(defun pmail-get-attr-names (&optional msg) 2122(defun pmail-get-attr-names (&optional msg)
2093 "Return the message attributes in a comma separated string. 2123 "Return the message attributes in a comma separated string.
@@ -2107,23 +2137,31 @@ If MSG is nil, use the current message."
2107 2137
2108(defun pmail-get-keywords (&optional msg) 2138(defun pmail-get-keywords (&optional msg)
2109 "Return the message keywords in a comma separated string. 2139 "Return the message keywords in a comma separated string.
2110MSG, if set identifies the message number to use. The current 2140MSG, if non-nil, identifies the message number to use.
2111mail message will be used otherwise." 2141If nil, that means the current message."
2112 (pmail-get-header pmail-keyword-header msg)) 2142 (pmail-get-header pmail-keyword-header msg))
2113 2143
2114(defun pmail-display-labels () 2144(defun pmail-get-labels (&optional msg)
2115 "Update the current messages's attributes and keywords in mode line." 2145 "Return a string with the labels (attributes and keywords) of msg MSG.
2146It is put in comma-separated form.
2147MSG, if non-nil, identifies the message number to use.
2148If nil, that means the current message."
2116 (let (blurb attr-names keywords) 2149 (let (blurb attr-names keywords)
2117 ;; Combine the message attributes and keywords 2150 ;; Combine the message attributes and keywords
2118 ;; into a comma-separated list. 2151 ;; into a comma-separated list.
2119 (setq attr-names (pmail-get-attr-names pmail-current-message) 2152 (setq attr-names (pmail-get-attr-names pmail-current-message)
2120 keywords (pmail-get-keywords pmail-current-message)) 2153 keywords (pmail-get-keywords pmail-current-message))
2121 (setq blurb 2154 (if (string= keywords "")
2122 (cond 2155 (setq keywords nil))
2123 ((and attr-names keywords) (concat " " attr-names ", " keywords)) 2156 (cond
2124 (attr-names (concat " " attr-names)) 2157 ((and attr-names keywords) (concat " " attr-names ", " keywords))
2125 (keywords (concat " " keywords)) 2158 (attr-names (concat " " attr-names))
2126 (t ""))) 2159 (keywords (concat " " keywords))
2160 (t ""))))
2161
2162(defun pmail-display-labels ()
2163 "Update the current messages's attributes and keywords in mode line."
2164 (let ((blurb (pmail-get-labels)))
2127 (setq mode-line-process 2165 (setq mode-line-process
2128 (format " %d/%d%s" 2166 (format " %d/%d%s"
2129 pmail-current-message pmail-total-messages blurb)) 2167 pmail-current-message pmail-total-messages blurb))
@@ -2155,6 +2193,7 @@ change; nil means current message."
2155 (let ((value (pmail-get-attr-value attr state)) 2193 (let ((value (pmail-get-attr-value attr state))
2156 (inhibit-read-only t) 2194 (inhibit-read-only t)
2157 limit 2195 limit
2196 altered
2158 msgbeg) 2197 msgbeg)
2159 (or msgnum (setq msgnum pmail-current-message)) 2198 (or msgnum (setq msgnum pmail-current-message))
2160 (when (> msgnum 0) 2199 (when (> msgnum 0)
@@ -2190,6 +2229,7 @@ change; nil means current message."
2190 (forward-char attr)) 2229 (forward-char attr))
2191 ;; Change this attribute. 2230 ;; Change this attribute.
2192 (when (/= value (char-after)) 2231 (when (/= value (char-after))
2232 (setq altered t)
2193 (delete-char 1) 2233 (delete-char 1)
2194 (insert value))) 2234 (insert value)))
2195 ;; Otherwise add a header line to record the attributes 2235 ;; Otherwise add a header line to record the attributes
@@ -2197,9 +2237,15 @@ change; nil means current message."
2197 (let ((header-value "--------")) 2237 (let ((header-value "--------"))
2198 (aset header-value attr value) 2238 (aset header-value attr value)
2199 (goto-char (if limit (- limit 1) (point-max))) 2239 (goto-char (if limit (- limit 1) (point-max)))
2240 (setq altered (/= value ?-))
2200 (insert pmail-attribute-header ": " header-value "\n")))))) 2241 (insert pmail-attribute-header ": " header-value "\n"))))))
2201 (if (= msgnum pmail-current-message) 2242 (if (= msgnum pmail-current-message)
2202 (pmail-display-labels))))))) 2243 (pmail-display-labels))))
2244 ;; If we made a significant change in an attribute,
2245 ;; mark pmail-buffer modified, so it will be (1) saved
2246 ;; and (2) displayed in the mode line.
2247 (if altered
2248 (set-buffer-modified-p t)))))
2203 2249
2204(defun pmail-message-attr-p (msg attrs) 2250(defun pmail-message-attr-p (msg attrs)
2205 "Return t if the attributes header for message MSG matches regexp ATTRS. 2251 "Return t if the attributes header for message MSG matches regexp ATTRS.
@@ -2220,18 +2266,6 @@ This function assumes the Pmail buffer is unswapped."
2220 "Test the unseen attribute for message MSGNUM. 2266 "Test the unseen attribute for message MSGNUM.
2221Return non-nil if the unseen attribute is set, nil otherwise." 2267Return non-nil if the unseen attribute is set, nil otherwise."
2222 (pmail-message-attr-p msgnum "......U")) 2268 (pmail-message-attr-p msgnum "......U"))
2223
2224;; Return t if the attributes/keywords line of msg number MSG
2225;; contains a match for the regexp LABELS.
2226(defun pmail-message-labels-p (msg labels)
2227 ;;;??? BROKEN
2228 (error "pmail-message-labels-p has not been updated for Pmail")
2229 (save-excursion
2230 (save-restriction
2231 (widen)
2232 (goto-char (pmail-msgbeg msg))
2233 (forward-char 3)
2234 (re-search-backward labels (prog1 (point) (end-of-line)) t))))
2235 2269
2236;;;; *** Pmail Message Selection And Support *** 2270;;;; *** Pmail Message Selection And Support ***
2237 2271
@@ -2250,7 +2284,9 @@ swapped state, i.e. it currently contains a single decoded
2250message rather than an entire message collection, nil otherwise." 2284message rather than an entire message collection, nil otherwise."
2251 (let (result) 2285 (let (result)
2252 (when (pmail-buffers-swapped-p) 2286 (when (pmail-buffers-swapped-p)
2253 (buffer-swap-text pmail-view-buffer) 2287 (let ((modp (buffer-modified-p)))
2288 (buffer-swap-text pmail-view-buffer)
2289 (set-buffer-modified-p modp))
2254 (setq buffer-swapped-with nil 2290 (setq buffer-swapped-with nil
2255 result pmail-current-message)) 2291 result pmail-current-message))
2256 result)) 2292 result))
@@ -2275,6 +2311,29 @@ display it. Return nil."
2275(defun pmail-msgbeg (n) 2311(defun pmail-msgbeg (n)
2276 (marker-position (aref pmail-message-vector n))) 2312 (marker-position (aref pmail-message-vector n)))
2277 2313
2314(defun pmail-apply-in-message (msgnum function &rest args)
2315 "Call FUNCTION on ARGS while narrowed to message MSGNUM.
2316Point is at the start of the message.
2317This returns what the call to FUNCTION returns.
2318If MSGNUM is nil, use the current message."
2319 (with-current-buffer pmail-buffer
2320 (or msgnum (setq msgnum pmail-current-message))
2321 (when (> msgnum 0)
2322 (let (msgbeg msgend)
2323 (setq msgbeg (pmail-msgbeg msgnum))
2324 (setq msgend (pmail-msgend msgnum))
2325 ;; All access to the pmail-buffer's local variables is now finished...
2326 (save-excursion
2327 ;; ... so it is ok to go to a different buffer.
2328 (if (pmail-buffers-swapped-p) (set-buffer pmail-view-buffer))
2329 (save-restriction
2330 (widen)
2331 (save-excursion
2332 (goto-char msgbeg)
2333 (save-restriction
2334 (narrow-to-region msgbeg msgend)
2335 (apply function args)))))))))
2336
2278(defun pmail-widen-to-current-msgbeg (function) 2337(defun pmail-widen-to-current-msgbeg (function)
2279 "Call FUNCTION with point at start of internal data of current message. 2338 "Call FUNCTION with point at start of internal data of current message.
2280Assumes that bounds were previously narrowed to display the message in Pmail. 2339Assumes that bounds were previously narrowed to display the message in Pmail.
@@ -2481,7 +2540,9 @@ Ask the user whether to add that list name to `mail-mailing-lists'."
2481If so restore the actual mbox message collection." 2540If so restore the actual mbox message collection."
2482 (with-current-buffer pmail-buffer 2541 (with-current-buffer pmail-buffer
2483 (when (pmail-buffers-swapped-p) 2542 (when (pmail-buffers-swapped-p)
2484 (buffer-swap-text pmail-view-buffer) 2543 (let ((modp (buffer-modified-p)))
2544 (buffer-swap-text pmail-view-buffer)
2545 (set-buffer-modified-p modp))
2485 (setq buffer-swapped-with nil)))) 2546 (setq buffer-swapped-with nil))))
2486 2547
2487(defun pmail-widen () 2548(defun pmail-widen ()
@@ -2561,7 +2622,6 @@ The current mail message becomes the message displayed."
2561 (pmail-swap-buffers-maybe) 2622 (pmail-swap-buffers-maybe)
2562 (setq beg (pmail-msgbeg msg) 2623 (setq beg (pmail-msgbeg msg)
2563 end (pmail-msgend msg)) 2624 end (pmail-msgend msg))
2564 (widen)
2565 (narrow-to-region beg end) 2625 (narrow-to-region beg end)
2566 (goto-char beg) 2626 (goto-char beg)
2567 (setq body-start (search-forward "\n\n" nil t)) 2627 (setq body-start (search-forward "\n\n" nil t))
@@ -2572,25 +2632,29 @@ The current mail message becomes the message displayed."
2572 coding-system (pmail-get-coding-system)) 2632 coding-system (pmail-get-coding-system))
2573 (if character-coding 2633 (if character-coding
2574 (setq character-coding (downcase character-coding))) 2634 (setq character-coding (downcase character-coding)))
2575 (widen)
2576 (narrow-to-region beg end) 2635 (narrow-to-region beg end)
2577 ;; Decode the message body into an empty view buffer using a 2636 ;; Decode the message body into an empty view buffer using a
2578 ;; unibyte temporary buffer where the character decoding takes 2637 ;; unibyte temporary buffer where the character decoding takes
2579 ;; place. 2638 ;; place.
2580 (with-current-buffer pmail-view-buffer 2639 (with-current-buffer pmail-view-buffer
2581 (erase-buffer)) 2640 (erase-buffer))
2582 (with-temp-buffer 2641 (if (null character-coding)
2583 (set-buffer-multibyte nil) 2642 ;; Do it directly since that is fast.
2584 (insert-buffer-substring mbox-buf body-start end) 2643 (pmail-decode-region body-start end coding-system view-buf)
2585 (cond 2644 ;; Can this be done directly, skipping the temp buffer?
2586 ((string= character-coding "quoted-printable") 2645 (with-temp-buffer
2587 (mail-unquote-printable-region (point-min) (point-max))) 2646 (set-buffer-multibyte nil)
2588 ((and (string= character-coding "base64") is-text-message) 2647 (insert-buffer-substring mbox-buf body-start end)
2589 (base64-decode-region (point-min) (point-max))) 2648 (cond
2590 ((eq character-coding 'uuencode) 2649 ((string= character-coding "quoted-printable")
2591 (error "Not supported yet.")) 2650 (mail-unquote-printable-region (point-min) (point-max)))
2592 (t)) 2651 ((and (string= character-coding "base64") is-text-message)
2593 (pmail-decode-region (point-min) (point-max) coding-system view-buf)) 2652 (base64-decode-region (point-min) (point-max)))
2653 ((eq character-coding 'uuencode)
2654 (error "Not supported yet"))
2655 (t))
2656 (pmail-decode-region (point-min) (point-max)
2657 coding-system view-buf)))
2594 ;; Copy the headers to the front of the message view buffer. 2658 ;; Copy the headers to the front of the message view buffer.
2595 (with-current-buffer pmail-view-buffer 2659 (with-current-buffer pmail-view-buffer
2596 (goto-char (point-min))) 2660 (goto-char (point-min)))
@@ -2608,7 +2672,9 @@ The current mail message becomes the message displayed."
2608 ;; Update the mode-line with message status information and swap 2672 ;; Update the mode-line with message status information and swap
2609 ;; the view buffer/mail buffer contents. 2673 ;; the view buffer/mail buffer contents.
2610 (pmail-display-labels) 2674 (pmail-display-labels)
2611 (buffer-swap-text pmail-view-buffer) 2675 (let ((modp (buffer-modified-p)))
2676 (buffer-swap-text pmail-view-buffer)
2677 (set-buffer-modified-p modp))
2612 (setq buffer-swapped-with pmail-view-buffer) 2678 (setq buffer-swapped-with pmail-view-buffer)
2613 (run-hooks 'pmail-show-message-hook)) 2679 (run-hooks 'pmail-show-message-hook))
2614 blurb)) 2680 blurb))
@@ -2690,7 +2756,7 @@ Called when a new message is displayed."
2690 (pmail-delete-forward) 2756 (pmail-delete-forward)
2691 (if (string= "/dev/null" folder) 2757 (if (string= "/dev/null" folder)
2692 (pmail-delete-message) 2758 (pmail-delete-message)
2693 (pmail-output-to-babyl-file folder 1 t) 2759 (pmail-output folder 1 t)
2694 (setq d nil)))) 2760 (setq d nil))))
2695 (setq d (cdr d)))))) 2761 (setq d (cdr d))))))
2696 2762
@@ -2767,50 +2833,11 @@ or forward if N is negative."
2767 (setq high mid)) 2833 (setq high mid))
2768 (setq mid (+ low (/ (- high low) 2)))) 2834 (setq mid (+ low (/ (- high low) 2))))
2769 (if (>= where (pmail-msgbeg high)) high low))) 2835 (if (>= where (pmail-msgbeg high)) high low)))
2770 2836
2771(defun pmail-message-recipients-p (msg recipients &optional primary-only)
2772 ;;;??? BROKEN
2773 (error "pmail-message-recipients-p has not been updated for Pmail")
2774 (save-restriction
2775 (goto-char (pmail-msgbeg msg))
2776 (search-forward "\n*** EOOH ***\n")
2777 (narrow-to-region (point) (progn (search-forward "\n\n") (point)))
2778 (or (string-match recipients (or (mail-fetch-field "To") ""))
2779 (string-match recipients (or (mail-fetch-field "From") ""))
2780 (if (not primary-only)
2781 (string-match recipients (or (mail-fetch-field "Cc") ""))))))
2782
2783(defun pmail-message-regexp-p (n regexp)
2784 "Return t, if for message number N, regexp REGEXP matches in the header."
2785 ;;;??? BROKEN
2786 (error "pmail-message-regexp-p has not been updated for Pmail")
2787 (let ((beg (pmail-msgbeg n))
2788 (end (pmail-msgend n)))
2789 (goto-char beg)
2790 (forward-line 1)
2791 (save-excursion
2792 (save-restriction
2793 (if (prog1 (= (following-char) ?0)
2794 (forward-line 2)
2795 ;; If there's a Summary-line in the (otherwise empty)
2796 ;; header, we didn't yet get past the EOOH line.
2797 (when (looking-at "^\\*\\*\\* EOOH \\*\\*\\*\n")
2798 (forward-line 1))
2799 (setq beg (point))
2800 (narrow-to-region (point) end))
2801 (progn
2802 (rfc822-goto-eoh)
2803 (setq end (point)))
2804 (setq beg (point))
2805 (search-forward "\n*** EOOH ***\n" end t)
2806 (setq end (1+ (match-beginning 0)))))
2807 (goto-char beg)
2808 (if pmail-enable-mime
2809 (funcall pmail-search-mime-header-function n regexp end)
2810 (re-search-forward regexp end t)))))
2811
2812(defun pmail-search-message (msg regexp) 2837(defun pmail-search-message (msg regexp)
2813 "Return non-nil, if for message number MSG, regexp REGEXP matches." 2838 "Return non-nil, if for message number MSG, regexp REGEXP matches."
2839 ;; This is adequate because its only caller, pmail-search,
2840 ;; unswaps the buffers.
2814 (goto-char (pmail-msgbeg msg)) 2841 (goto-char (pmail-msgbeg msg))
2815 (if pmail-enable-mime 2842 (if pmail-enable-mime
2816 (funcall pmail-search-mime-message-function msg regexp) 2843 (funcall pmail-search-mime-message-function msg regexp)
@@ -2928,11 +2955,11 @@ Interactively, empty argument means use same regexp used last time."
2928 (setq current (1+ current)))) 2955 (setq current (1+ current))))
2929 found)) 2956 found))
2930 2957
2931(defun pmail-current-subject () 2958(defun pmail-simplified-subject (&optional msgnum)
2932 "Return the current subject. 2959 "Return the simplified subject of message MSGNUM (or current message).
2933The subject is stripped of leading and trailing whitespace, and 2960Simplifying the subject means stripping leading and trailing whitespace,
2934of typical reply prefixes such as Re:." 2961and typical reply prefixes such as Re:."
2935 (let ((subject (or (mail-fetch-field "Subject") ""))) 2962 (let ((subject (or (pmail-get-header "Subject" msgnum) "")))
2936 (if (string-match "\\`[ \t]+" subject) 2963 (if (string-match "\\`[ \t]+" subject)
2937 (setq subject (substring subject (match-end 0)))) 2964 (setq subject (substring subject (match-end 0))))
2938 (if (string-match pmail-reply-regexp subject) 2965 (if (string-match pmail-reply-regexp subject)
@@ -2941,63 +2968,39 @@ of typical reply prefixes such as Re:."
2941 (setq subject (substring subject 0 (match-beginning 0)))) 2968 (setq subject (substring subject 0 (match-beginning 0))))
2942 subject)) 2969 subject))
2943 2970
2944(defun pmail-current-subject-regexp () 2971(defun pmail-simplified-subject-regexp ()
2945 "Return a regular expression matching the current subject. 2972 "Return a regular expression matching the current simplified subject.
2946The regular expression matches the subject header line of 2973The idea is to match it against simplified subjects of other messages."
2947messages about the same subject. The subject itself is stripped 2974 (let ((subject (pmail-simplified-subject)))
2948of leading and trailing whitespace, of typical reply prefixes
2949such as Re: and whitespace within the subject is replaced by a
2950regular expression matching whitespace in general in order to
2951take into account that subject header lines may include newlines
2952and more whitespace. The returned regular expressions contains
2953`pmail-reply-regexp' and ends with a newline."
2954 (let ((subject (pmail-current-subject)))
2955 ;; If Subject is long, mailers will break it into several lines at
2956 ;; arbitrary places, so replace whitespace with a regexp that will
2957 ;; match any sequence of spaces, TABs, and newlines.
2958 (setq subject (regexp-quote subject)) 2975 (setq subject (regexp-quote subject))
2976 ;; Hide commas so it will work ok if parsed as a comma-separated list
2977 ;; of regexps.
2959 (setq subject 2978 (setq subject
2960 (replace-regexp-in-string "[ \t\n]+" "[ \t\n]+" subject t t)) 2979 (replace-regexp-in-string "," "\054" subject t t))
2961 ;; Some mailers insert extra spaces after "Subject:", so allow any 2980 (concat "\\`" subject "\\'")))
2962 ;; amount of them.
2963 (concat "^Subject:[ \t]+"
2964 (if (string= "\\`" (substring pmail-reply-regexp 0 2))
2965 (substring pmail-reply-regexp 2)
2966 pmail-reply-regexp)
2967 subject "[ \t]*\n")))
2968 2981
2969(defun pmail-next-same-subject (n) 2982(defun pmail-next-same-subject (n)
2970 "Go to the next mail message having the same subject header. 2983 "Go to the next mail message having the same subject header.
2971With prefix argument N, do this N times. 2984With prefix argument N, do this N times.
2972If N is negative, go backwards instead." 2985If N is negative, go backwards instead."
2973 (interactive "p") 2986 (interactive "p")
2974 (let ((search-regexp (pmail-current-subject-regexp)) 2987 (let ((subject (pmail-simplified-subject))
2975 (forward (> n 0)) 2988 (forward (> n 0))
2976 (i pmail-current-message) 2989 (i pmail-current-message)
2977 (case-fold-search t)
2978 found) 2990 found)
2979 (save-excursion 2991 (while (and (/= n 0)
2980 (save-restriction 2992 (if forward
2981 (widen) 2993 (< i pmail-total-messages)
2982 (while (and (/= n 0) 2994 (> i 1)))
2995 (let (done)
2996 (while (and (not done)
2983 (if forward 2997 (if forward
2984 (< i pmail-total-messages) 2998 (< i pmail-total-messages)
2985 (> i 1))) 2999 (> i 1)))
2986 (let (done) 3000 (setq i (if forward (1+ i) (1- i)))
2987 (while (and (not done) 3001 (setq done (string-equal subject (pmail-simplified-subject i))))
2988 (if forward 3002 (if done (setq found i)))
2989 (< i pmail-total-messages) 3003 (setq n (if forward (1- n) (1+ n))))
2990 (> i 1)))
2991 (setq i (if forward (1+ i) (1- i)))
2992 (goto-char (pmail-msgbeg i))
2993 (search-forward "\n*** EOOH ***\n")
2994 (let ((beg (point)) end)
2995 (search-forward "\n\n")
2996 (setq end (point))
2997 (goto-char beg)
2998 (setq done (re-search-forward search-regexp end t))))
2999 (if done (setq found i)))
3000 (setq n (if forward (1- n) (1+ n))))))
3001 (if found 3004 (if found
3002 (pmail-show-message-maybe found) 3005 (pmail-show-message-maybe found)
3003 (error "No %s message with same subject" 3006 (error "No %s message with same subject"
@@ -3855,7 +3858,7 @@ TOKEN and INDENT are not used."
3855TEXT and INDENT are not used." 3858TEXT and INDENT are not used."
3856 (speedbar-with-attached-buffer 3859 (speedbar-with-attached-buffer
3857 (message "Moving message to %s" token) 3860 (message "Moving message to %s" token)
3858 (pmail-output-to-babyl-file token))) 3861 (pmail-output token)))
3859 3862
3860; Functions for setting, getting and encoding the POP password. 3863; Functions for setting, getting and encoding the POP password.
3861; The password is encoded to prevent it from being easily accessible 3864; The password is encoded to prevent it from being easily accessible