+Fri Dec 3 20:34:11 1999 Lars Magne Ingebrigtsen <larsi@menja.ifi.uio.no>
+
+ * gnus.el: Pterodactyl Gnus v5.8.2 is released.
+
+Fri Dec 3 20:09:41 1999 Lars Magne Ingebrigtsen <larsi@menja.ifi.uio.no>
+
+ * gnus.el: Pterodactyl Gnus v5.8.1 is released.
+
+1999-11-11 Hrvoje Niksic <hniksic@iskon.hr>
+
+ * mml.el (mml-insert-tag): Don't close the tag.
+ (mml-insert-empty-tag): New function.
+ (mml-attach-file): Use mml-insert-empty-tag instead of
+ mml-insert-tag.
+ (mml-attach-buffer): Ditto.
+ (mml-attach-external): Ditto.
+ (mml-insert-multipart): Ditto.
+
+1999-12-03 08:49:53 Shenghuo ZHU <zsh@cs.rochester.edu>
+
+ * nnfolder.el (nnfolder-request-article): Return -1 if not find
+ the article number.
+
+1999-12-03 01:12:41 Shenghuo ZHU <zsh@cs.rochester.edu>
+
+ * gnus.el (gnus-find-method-for-group): The method of a new group
+ is not the native one.
+
+1999-12-03 01:26:55 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * gnus-art.el (gnus-button-embedded-url): Always call browse-url.
+
+1999-12-02 18:00:15 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * nnultimate.el (nnultimate-retrieve-headers): Use
+ mm-with-unibyte-current-buffer.
+ (nnultimate-request-article): Ditto.
+
+1999-12-02 14:57:46 Shenghuo ZHU <zsh@cs.rochester.edu>
+
+ * nntp.el (nntp-retrieve-groups): Set to process buffer.
+
+1999-12-02 11:14:50 Shenghuo ZHU <zsh@cs.rochester.edu>
+
+ * mm-util.el (mm-with-unibyte-current-buffer): New macro.
+ * nnweb.el (nnweb-retrieve-headers): Use it.
+ (nnweb-request-article): Use it.
+
+ * nnweb.el (nnweb-dejanews-create-mapping): Set a default date in
+ case matching failed.
+
+1999-12-02 John Wiegley <jwiegley@inprise.com>
+
+ * mail-source.el (mail-source-keyword-map): Add backslash to
+ Delete-flag.
+
+1999-12-02 07:24:35 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * gnus-sum.el (gnus-group-charset-alist): Default nnweb groups to
+ Latin-1.
+ (gnus-group-charset-alist): No, don't.
+
+ * nnweb.el (nnweb-init): Make the buffer unibyte.
+
+1999-12-01 23:02:48 Shenghuo ZHU <zsh@cs.rochester.edu>
+
+ * mail-source.el (mail-source-set-common-1): Fix to get the
+ default value.
+
+1999-12-02 00:27:46 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * nnslashdot.el (nnslashdot-read-groups): Unibyte.
+
+ * nnultimate.el (nnultimate-request-list): Use unibyte.
+
+ * gnus-uu.el (gnus-uu-grab-articles): Bind
+ gnus-display-mime-function to nil.
+
+ * message.el (message-send-mail-with-sendmail): Use the
+ user-mail-address variable.
+
+ * gnus-art.el (gnus-ignored-headers): More headers.
+
+ * message.el (message-shorten-1): Use list.
+
+1999-12-01 21:59:36 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * gnus-msg.el (gnus-configure-posting-styles): Ignore nil
+ signatures.
+
+ * nnweb.el (nnweb-dejanews-create-mapping): Get the data.
+ (nnweb-dejanews-create-mapping): Do the properish date.
+
+1999-12-01 17:41:21 Shenghuo ZHU <zsh@cs.rochester.edu>
+
+ * mail-source.el (mail-source-common-keyword-map): New variable.
+ (mail-source-bind-common): New macro.
+ (mail-source-fetch): Support plugged mail source.
+ * gnus-int.el (gnus-request-scan): Use them.
+
+1999-12-01 21:59:36 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * mm-view.el (mm-inline-message): Check whether charset is a
+ string.
+
+ * nnslashdot.el (nnslashdot-request-post): Insert <p>'s.
+
+ * message.el (message-mode-map): Changed keystroke for
+ message-yank-buffer.
+
+1999-11-26 Hrvoje Niksic <hniksic@iskon.hr>
+
+ * message.el (message-shorten-references): Cut references to 31
+ elements, then either fold them or shorten them to 988 characters.
+ (message-shorten-1): New function.
+ (message-cater-to-broken-inn): New variable.
+
+1999-12-01 21:47:10 Eric Marsden <emarsden@mail.dotcom.fr>
+
+ * nnslashdot.el (nnslashdot-lose): New function.
+
+1999-12-01 21:08:48 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * mm-view.el (mm-inline-message): Not the right type of charset is
+ being fetched here. Let the group charset rule.
+ (mm-inline-message): Ignore us-ascii.
+
+1999-11-24 Carsten Leonhardt <leo@arioch.oche.de>
+
+ * mail-source.el (mail-source-fetch-maildir): work around the
+ ommitted "file-regular-p" in efs/ange-ftp
+
+1999-12-01 19:59:25 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * mml.el (mml-generate-mime-1): Don't insert extra empty line.
+ (mml-generate-mime-1): Use the encoding param.
+
+ * gnus-sum.el (gnus-summary-show-article): Don't bind gnus-visual.
+
+ * gnus-cache.el (gnus-cache-possibly-enter-article): Require
+ gnus-art before binding its variables.
+
+ * gnus-art.el (gnus-article-prepare-display): Run the prepare
+ after the MIME.
+
+1999-12-01 19:48:14 Rupa Schomaker <rupa-list@rupa.com>
+
+ * message.el (message-clone-locals): Use it.
+
+ * gnus-msg.el (gnus-configure-posting-styles): Make
+ user-mail-address local.
+
+1999-11-20 Simon Josefsson <jas@pdc.kth.se>
+
+ * gnus-start.el (gnus-get-unread-articles): Scan each method only
+ once.
+
+1999-12-01 17:37:18 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * message.el (message-generate-new-buffer-clone-locals): Use varstr.
+ (message-clone-locals): Ditto.
+
+ * gnus-sum.el (gnus-summary-enter-digest-group): Have the digest
+ group inherit reply-to or from.
+
+1999-12-01 13:04:09 Shenghuo ZHU <zsh@cs.rochester.edu>
+
+ * gnus-sum.el (gnus-summary-show-article): Support numbered ARG
+ for charset.
+ (gnus-summary-show-article-charset-alist): New variable.
+
+ * mm-bodies.el (mm-decode-string): Support gnus-all and
+ gnus-unknown.
+ (mm-decode-body): Ditto.
+ * rfc2047.el (rfc2047-decode): Ditto.
+
+1999-12-01 17:37:18 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * mail-source.el (mail-source-delete-incoming): Change default to
+ t.
+
Wed Dec 1 16:31:31 1999 Lars Magne Ingebrigtsen <larsi@menja.ifi.uio.no>
* gnus.el: Pterodactyl Gnus v0.99 is released.
(defvar srcdir (or (getenv "srcdir") "."))
(push srcdir load-path)
+;(push "/usr/share/emacs/site-lisp" load-path)
(load (expand-file-name "lpath.el" srcdir) nil t)
(defalias 'device-sound-enabled-p 'ignore)
"^X-Sun-Charset:" "^X-Accept-Language:" "^X-Envelope-Sender:"
"^List-[A-Za-z]+:" "^X-Listprocessor-Version:"
"^X-Received:" "^X-Distribute:" "^X-Sequence:" "^X-Juno-Line-Breaks:"
- "^X-Notes-Item:" "^X-MS-TNEF-Correlator:" "^x-uunet-gateway:")
+ "^X-Notes-Item:" "^X-MS-TNEF-Correlator:" "^x-uunet-gateway:"
+ "^X-Received:" "^Content-length:" "X-precedence:")
"*All headers that start with this regexp will be hidden.
This variable can also be a list of regexps of headers to be ignored.
If `gnus-visible-headers' is non-nil, this variable will be ignored."
(setq buffer-read-only nil
gnus-article-wash-types nil)
(gnus-run-hooks 'gnus-tmp-internal-hook)
- (gnus-run-hooks 'gnus-article-prepare-hook)
(when gnus-display-mime-function
- (funcall gnus-display-mime-function))))
+ (funcall gnus-display-mime-function))
+ (gnus-run-hooks 'gnus-article-prepare-hook)))
;;;
;;; Gnus MIME viewing functions
(defun gnus-button-embedded-url (address)
"Browse ADDRESS."
- ;; In Emacs 20, `browse-url-browser-function' may be an alist.
- (if (listp browse-url-browser-function)
- (browse-url (gnus-strip-whitespace address))
- (funcall browse-url-browser-function (gnus-strip-whitespace address))))
+ (browse-url (gnus-strip-whitespace address)))
;;; Next/prev buttons in the article buffer.
t ; The article already is saved.
(save-excursion
(set-buffer nntp-server-buffer)
+ (require 'gnus-art)
(let ((gnus-use-cache nil)
(gnus-article-decode-hook nil))
(gnus-request-article-this-buffer number group))
(defun gnus-request-scan (group gnus-command-method)
"Request a SCAN being performed in GROUP from GNUS-COMMAND-METHOD.
If GROUP is nil, all groups on GNUS-COMMAND-METHOD are scanned."
- (when gnus-plugged
- (let ((gnus-command-method
- (if group (gnus-find-method-for-group group) gnus-command-method))
- (gnus-inhibit-demon t))
- (funcall (gnus-get-function gnus-command-method 'request-scan)
- (and group (gnus-group-real-name group))
- (nth 1 gnus-command-method)))))
+ (let ((gnus-command-method
+ (if group (gnus-find-method-for-group group) gnus-command-method))
+ (gnus-inhibit-demon t)
+ (mail-source-plugged gnus-plugged))
+ (if (or gnus-plugged (not (gnus-agent-method-p gnus-command-method)))
+ (funcall (gnus-get-function gnus-command-method 'request-scan)
+ (and group (gnus-group-real-name group))
+ (nth 1 gnus-command-method)))))
(defsubst gnus-request-update-info (info gnus-command-method)
"Request that GNUS-COMMAND-METHOD update INFO."
((eq 'signature (car result))
(set (make-local-variable 'message-signature) nil)
(set (make-local-variable 'message-signature-file) nil)
- `(lambda ()
- (save-excursion
- (let ((message-signature ,(cdr result)))
- (when message-signature
- (message-insert-signature))))))
+ (if (not (cdr result))
+ 'ignore
+ `(lambda ()
+ (save-excursion
+ (let ((message-signature ,(cdr result)))
+ (when message-signature
+ (message-insert-signature)))))))
(t
(let ((header
(if (symbolp (car result))
(when (or name address)
(add-hook 'message-setup-hook
`(lambda ()
+ (set (make-local-variable 'user-mail-address)
+ ,(or (cdr address) user-mail-address))
(let ((user-full-name ,(or (cdr name) (user-full-name)))
(user-mail-address
,(or (cdr address) user-mail-address)))
gnus-activate-foreign-newsgroups)
(t 0))
level))
- info group active method retrievegroups)
+ scanned-methods info group active method retrievegroups)
(gnus-message 5 "Checking new news...")
(while newsrc
(setcdr (assoc method retrievegroups)
(cons group (cdr (assoc method retrievegroups))))
(push (list method group) retrievegroups))
- (setq active (gnus-activate-group group 'scan))
+ (if (member method scanned-methods)
+ (setq active (gnus-activate-group group))
+ (setq active (gnus-activate-group group 'scan))
+ (push method scanned-methods))
(inline (gnus-close-group group))))))
;; Get the number of unread articles in the group.
gnus-emphasis-highlight-words)))))
:group 'gnus-summary-visual)
+(defcustom gnus-summary-show-article-charset-alist
+ nil
+ "Alist of number and charset.
+The article will be shown with the charset corresponding to the
+numbered argument.
+For example: ((1 . cn-gb-2312) (2 . big5))."
+ :type '(repeat (cons (number :tag "Argument" 1)
+ (symbol :tag "Charset")))
+ :group 'gnus-charset)
+
+
;;; Internal variables
(defvar gnus-article-mime-handles nil)
(list (cons 'save-article-group ogroup))))
(case-fold-search t)
(buf (current-buffer))
- dig)
+ dig to-address)
(save-excursion
+ (set-buffer gnus-original-article-buffer)
+ ;; Have the digest group inherit the main mail address of
+ ;; the parent article.
+ (when (setq to-address (or (message-fetch-field "reply-to")
+ (message-fetch-field "from")))
+ (setq params (append (list (cons 'to-address to-address)))))
(setq dig (nnheader-set-temp-buffer " *gnus digest buffer*"))
(insert-buffer-substring gnus-original-article-buffer)
;; Remove lines that may lead nndoc to misinterpret the
(defun gnus-summary-show-article (&optional arg)
"Force re-fetching of the current article.
-If ARG (the prefix) is non-nil, show the raw article without any
-article massaging functions being run."
+If ARG (the prefix) is a number, show the article with the charset
+defined in `gnus-summary-show-article-charset-alist', or the charset
+inputed.
+If ARG (the prefix) is non-nil and not a number, show the raw article
+without any article massaging functions being run."
(interactive "P")
- (if (not arg)
- ;; Select the article the normal way.
- (gnus-summary-select-article nil 'force)
+ (cond
+ ((numberp arg)
+ (let ((gnus-newsgroup-charset
+ (or (cdr (assq arg gnus-summary-show-article-charset-alist))
+ (read-coding-system "Charset: ")))
+ (gnus-newsgroup-ignored-charsets 'gnus-all))
+ (gnus-summary-select-article nil 'force)))
+ ((not arg)
+ ;; Select the article the normal way.
+ (gnus-summary-select-article nil 'force))
+ (t
;; We have to require this here to make sure that the following
;; dynamic binding isn't shadowed by autoloading.
(require 'gnus-async)
gnus-article-prepare-hook
gnus-article-decode-hook
gnus-display-mime-function
- gnus-break-pages
- gnus-visual)
+ gnus-break-pages)
;; Destroy any MIME parts.
(when (gnus-buffer-live-p gnus-article-buffer)
(save-excursion
(set-buffer gnus-article-buffer)
(mm-destroy-parts gnus-article-mime-handles)))
- (gnus-summary-select-article nil 'force)))
+ (gnus-summary-select-article nil 'force))))
(gnus-summary-goto-subject gnus-current-article)
(gnus-summary-position-point))
(setq gnus-newsgroup-charset
(or gnus-newsgroup-ephemeral-charset
(and gnus-newsgroup-name
- (or (gnus-group-find-parameter gnus-newsgroup-name
- 'charset)
+ (or (gnus-group-find-parameter gnus-newsgroup-name 'charset)
(let ((alist gnus-group-charset-alist)
- elem (charset nil))
+ elem charset)
(while (setq elem (pop alist))
(when (and name
(string-match (car elem) name))
(gnus-inhibit-treatment t)
has-been-begin article result-file result-files process-state
gnus-summary-display-article-function
- gnus-article-prepare-hook
+ gnus-article-prepare-hook gnus-display-mime-function
article-series files)
(while (and articles
:link '(custom-manual "(gnus)Exiting Gnus")
:group 'gnus)
-(defconst gnus-version-number "0.99"
+(defconst gnus-version-number "5.8.2"
"Version number for this version of Gnus.")
-(defconst gnus-version (format "Pterodactyl Gnus v%s" gnus-version-number)
+(defconst gnus-version (format "Gnus v%s" gnus-version-number)
"Version string for this version of Gnus.")
(defcustom gnus-inhibit-startup-message nil
(or gnus-override-method
(and (not group)
gnus-select-method)
+ (and (not (gnus-group-entry group)) ;; a new group
+ (gnus-group-name-to-method group))
(let ((info (or info (gnus-get-info group)))
method)
(if (or (not info)
:group 'mail-source
:type 'integer)
-(defcustom mail-source-delete-incoming nil
+(defcustom mail-source-delete-incoming t
"*If non-nil, delete incoming files after handling."
:group 'mail-source
:type 'boolean)
"A dynamically bound string that says what the current mail source is.")
(eval-and-compile
+ (defvar mail-source-common-keyword-map
+ '((:plugged))
+ "Mapping from keywords to default values.
+Common keywords should be listed here.")
+
(defvar mail-source-keyword-map
'((file
(:prescript)
(:password)
(:mailbox "INBOX")
(:predicate "UNSEEN UNDELETED")
- (:fetchflag "\Deleted")
+ (:fetchflag "\\Deleted")
(:dontexpunge))
(webmail
(:subtype hotmail)
(defvar mail-source-password-cache nil)
+(defvar mail-source-plugged t)
+
;;; Functions
(eval-and-compile
(mail-source-value value)
(mail-source-value (cadr default)))))))
+(eval-and-compile
+ (defun mail-source-bind-common-1 ()
+ (let* ((defaults mail-source-common-keyword-map)
+ default bind)
+ (while (setq default (pop defaults))
+ (push (list (mail-source-strip-keyword (car default))
+ nil)
+ bind))
+ bind)))
+
+(defun mail-source-set-common-1 (source)
+ (let* ((type (pop source))
+ (defaults mail-source-common-keyword-map)
+ (defaults-1 (cdr (assq type mail-source-keyword-map)))
+ default value keyword)
+ (while (setq default (pop defaults))
+ (set (mail-source-strip-keyword (setq keyword (car default)))
+ (if (setq value (plist-get source keyword))
+ (mail-source-value value)
+ (if (setq value (assq keyword defaults-1))
+ (mail-source-value (cadr value))
+ (mail-source-value (cadr default))))))))
+
+(defmacro mail-source-bind-common (source &rest body)
+ "Return a `let' form that binds all common variables.
+See `mail-source-bind'."
+ `(let ,(mail-source-bind-common-1)
+ (mail-source-set-common-1 source)
+ ,@body))
+
+(put 'mail-source-bind-common 'lisp-indent-function 1)
+(put 'mail-source-bind-common 'edebug-form-spec '(form body))
+
(defun mail-source-value (value)
"Return the value of VALUE."
(cond
CALLBACK will be called with the name of the file where (some of)
the mail from SOURCE is put.
Return the number of files that were found."
- (save-excursion
- (let ((function (cadr (assq (car source) mail-source-fetcher-alist)))
- (found 0))
- (unless function
- (error "%S is an invalid mail source specification" source))
- ;; If there's anything in the crash box, we do it first.
- (when (file-exists-p mail-source-crash-box)
- (message "Processing mail from %s..." mail-source-crash-box)
- (setq found (mail-source-callback
- callback mail-source-crash-box)))
- (+ found
- (condition-case err
- (funcall function source callback)
- (error
- (unless (yes-or-no-p
- (format "Mail source error (%s). Continue? " err))
- (error "Cannot get new mail."))
- 0))))))
+ (mail-source-bind-common source
+ (if (or mail-source-plugged plugged)
+ (save-excursion
+ (let ((function (cadr (assq (car source) mail-source-fetcher-alist)))
+ (found 0))
+ (unless function
+ (error "%S is an invalid mail source specification" source))
+ ;; If there's anything in the crash box, we do it first.
+ (when (file-exists-p mail-source-crash-box)
+ (message "Processing mail from %s..." mail-source-crash-box)
+ (setq found (mail-source-callback
+ callback mail-source-crash-box)))
+ (+ found
+ (condition-case err
+ (funcall function source callback)
+ (error
+ (unless (yes-or-no-p
+ (format "Mail source error (%s). Continue? " err))
+ (error "Cannot get new mail."))
+ 0))))))))
(defun mail-source-make-complex-temp-name (prefix)
(let ((newname (make-temp-name prefix))
(let ((found 0)
(mail-source-string (format "maildir:%s" path)))
(dolist (file (directory-files path t))
- (when (and (file-regular-p file)
+ (when (and (not (file-directory-p file))
(not (if function
(funcall function file mail-source-crash-box)
(rename-file file mail-source-crash-box))))
(const use)
(const ask)))
-;; stuff relating to broken sendmail in MMDF
(defcustom message-sendmail-f-is-evil nil
- "*Non-nil means that \"-f username\" should not be added to the sendmail
-command line, because it is even more evil than leaving it out."
+ "*Non-nil means that \"-f username\" should not be added to the sendmail command line.
+Doing so would be even more evil than leaving it out."
:group 'message-sending
:type 'boolean)
:group 'message-sending
:type '(repeat string))
+(defvar message-cater-to-broken-inn t
+ "Non-nil means Gnus should not fold the `References' header.
+Folding `References' makes ancient versions of INN create incorrect
+NOV lines.")
+
(defvar gnus-post-method)
(defvar gnus-select-method)
(defcustom message-post-method
(define-key message-mode-map "\C-c\C-n" 'message-insert-newsgroups)
(define-key message-mode-map "\C-c\C-y" 'message-yank-original)
- (define-key message-mode-map "\C-c\C-Y" 'message-yank-buffer)
+ (define-key message-mode-map "\C-c\M-\C-y" 'message-yank-buffer)
(define-key message-mode-map "\C-c\C-q" 'message-fill-yanked-message)
(define-key message-mode-map "\C-c\C-w" 'message-insert-signature)
(define-key message-mode-map "\C-c\M-h" 'message-insert-headers)
(defun message-send-mail-with-sendmail ()
"Send off the prepared buffer with sendmail."
(let ((errbuf (if message-interactive
- (generate-new-buffer " sendmail errors")
+ (message-generate-new-buffer-clone-locals " sendmail errors")
0))
resend-to-addresses delimline)
(let ((case-fold-search t))
;; But some systems are more broken with -f, so
;; we'll let users override this.
(if (null message-sendmail-f-is-evil)
- (list "-f" (user-login-name)))
+ (list "-f"
+ (if (null user-mail-address)
+ (user-login-name)
+ user-mail-address)))
;; These mean "report errors by mail"
;; and "deliver in background".
(if (null message-interactive) '("-oem" "-odb"))
(defun message-fill-header (header value)
(let ((begin (point))
- (fill-column 990)
+ (fill-column 78)
(fill-prefix "\t"))
(insert (capitalize (symbol-name header))
": "
(replace-match " " t t))
(goto-char (point-max)))))
+(defun message-shorten-1 (list cut surplus)
+ ;; Cut SURPLUS elements out of LIST, beginning with CUTth one.
+ (setcdr (nthcdr (- cut 2) list)
+ (nthcdr (+ (- cut 2) surplus 1) list)))
+
(defun message-shorten-references (header references)
- "Limit REFERENCES to be shorter than 988 characters."
- (let ((max 988)
- (cut 4)
+ "Trim REFERENCES to be less than 31 Message-ID long, and fold them.
+If folding is disallowed, also check that the REFERENCES are less
+than 988 characters long, and if they are not, trim them until they are."
+ (let ((maxcount 31)
+ (count 0)
+ (cut 6)
refs)
(with-temp-buffer
(insert references)
(goto-char (point-min))
+ ;; Cons a list of valid references.
(while (re-search-forward "<[^>]+>" nil t)
(push (match-string 0) refs))
- (setq refs (nreverse refs))
- (while (> (length (mapconcat 'identity refs " ")) max)
- (when (< (length refs) (1+ cut))
- (decf cut))
- (setcdr (nthcdr cut refs) (cddr (nthcdr cut refs)))))
- (insert (capitalize (symbol-name header)) ": "
- (mapconcat 'identity refs " ") "\n")))
+ (setq refs (nreverse refs)
+ count (length refs)))
+
+ ;; If the list has more than MAXCOUNT elements, trim it by
+ ;; removing the CUTth element and the required number of
+ ;; elements that follow.
+ (when (> count maxcount)
+ (let ((surplus (- count maxcount)))
+ (message-shorten-1 refs cut surplus)
+ (decf count surplus)))
+
+ ;; If folding is disallowed, make sure the total length (including
+ ;; the spaces between) will be less than MAXSIZE characters.
+ (when message-cater-to-broken-inn
+ (let ((maxsize 988)
+ (totalsize (+ (apply #'+ (mapcar #'length refs))
+ (1- count)))
+ (surplus 0)
+ (ptr (nthcdr (1- cut) refs)))
+ ;; Decide how many elements to cut off...
+ (while (> totalsize maxsize)
+ (decf totalsize (1+ (length (car ptr))))
+ (incf surplus)
+ (setq ptr (cdr ptr)))
+ ;; ...and do it.
+ (when (> surplus 0)
+ (message-shorten-1 refs cut surplus))))
+
+ ;; Finally, collect the references back into a string and insert
+ ;; it into the buffer.
+ (let ((refstring (mapconcat #'identity refs " ")))
+ (if message-cater-to-broken-inn
+ (insert (capitalize (symbol-name header)) ": "
+ refstring "\n")
+ (message-fill-header header refstring)))))
(defun message-position-point ()
"Move point to where the user probably wants to find it."
(let ((oldbuf (current-buffer)))
(save-excursion
(set-buffer (generate-new-buffer name))
- (message-clone-locals oldbuf)
+ (message-clone-locals oldbuf varstr)
(current-buffer))))
-(defun message-clone-locals (buffer)
+(defun message-clone-locals (buffer &optional varstr)
"Clone the local variables from BUFFER to the current buffer."
(let ((locals (save-excursion
(set-buffer buffer)
(buffer-local-variables)))
- (regexp "^gnus\\|^nn\\|^message"))
+ (regexp "^gnus\\|^nn\\|^message\\|^user-mail-address"))
(mapcar
(lambda (local)
(when (and (consp local)
(car local)
- (string-match regexp (symbol-name (car local))))
+ (string-match regexp (symbol-name (car local)))
+ (or (null varstr)
+ (string-match varstr (symbol-name (car local)))))
(ignore-errors
(set (make-local-variable (car local))
(cdr local)))))
(delete-char 1)
(search-forward "\n\n")
(setq lines (buffer-substring (point-min) (1- (point))))
- (delete-region (point-min) (point))))))
+ (delete-region (point-min) (point))))))
(save-restriction
(message-narrow-to-headers-or-head)
(message-remove-header "Mime-Version")
(setq start nil)))
charset)))))))
-(defun mm-body-encoding (charset)
+(defun mm-body-encoding (charset &optional encoding)
"Do Content-Transfer-Encoding and return the encoding of the current buffer."
(let ((bits (mm-body-7-or-8)))
(cond
((eq charset mail-parse-charset)
bits)
(t
- (let ((encoding (or (cdr (assq charset mm-body-charset-encoding-alist))
+ (let ((encoding (or encoding
+ (cdr (assq charset mm-body-charset-encoding-alist))
(mm-qp-or-base64))))
(mm-encode-content-transfer-encoding encoding "text/plain")
encoding)))))
The characters in CHARSET should then be decoded."
(if (stringp charset)
(setq charset (intern (downcase charset))))
- (if (or (not charset) (memq charset mail-parse-ignored-charsets))
+ (if (or (not charset)
+ (eq 'gnus-all mail-parse-ignored-charsets)
+ (memq 'gnus-all mail-parse-ignored-charsets)
+ (memq charset mail-parse-ignored-charsets))
(setq charset mail-parse-charset))
(save-excursion
(when encoding
(mm-decode-content-transfer-encoding encoding type))
(when (featurep 'mule)
- (let (mule-charset)
- (when (and charset
- (setq mule-charset (mm-charset-to-coding-system charset))
+ (let ((mule-charset (mm-charset-to-coding-system charset)))
+ (if (and (not mule-charset)
+ (listp mail-parse-ignored-charsets)
+ (memq 'gnus-unknown mail-parse-ignored-charsets))
+ (setq mule-charset
+ (mm-charset-to-coding-system mail-parse-charset)))
+ (when (and charset mule-charset
;; buffer-file-coding-system
;;Article buffer is nil coding system
;;in XEmacs
"Decode STRING with CHARSET."
(if (stringp charset)
(setq charset (intern (downcase charset))))
- (if (or (not charset) (memq charset mail-parse-ignored-charsets))
+ (if (or (not charset)
+ (eq 'gnus-all mail-parse-ignored-charsets)
+ (memq 'gnus-all mail-parse-ignored-charsets)
+ (memq charset mail-parse-ignored-charsets))
(setq charset mail-parse-charset))
(or
(when (featurep 'mule)
- (let (mule-charset)
- (when (and charset
- (setq mule-charset (mm-charset-to-coding-system charset))
+ (let ((mule-charset (mm-charset-to-coding-system charset)))
+ (if (and (not mule-charset)
+ (listp mail-parse-ignored-charsets)
+ (memq 'gnus-unknown mail-parse-ignored-charsets))
+ (setq mule-charset
+ (mm-charset-to-coding-system mail-parse-charset)))
+ (when (and charset mule-charset
(mm-multibyte-p)
(or (not (eq mule-charset 'ascii))
(setq mule-charset mail-parse-charset)))
(put 'mm-with-unibyte-buffer 'lisp-indent-function 0)
(put 'mm-with-unibyte-buffer 'edebug-form-spec '(body))
+(defmacro mm-with-unibyte-current-buffer (&rest forms)
+ "Evaluate FORMS there like `progn' in current buffer."
+ (let ((multibyte (make-symbol "multibyte")))
+ `(if (or (string-match "XEmacs\\|Lucid" emacs-version)
+ (not (fboundp 'set-buffer-multibyte)))
+ (progn
+ ,@forms)
+ (let ((,multibyte (default-value 'enable-multibyte-characters)))
+ (unwind-protect
+ (let ((buffer-file-coding-system mm-binary-coding-system)
+ (coding-system-for-read mm-binary-coding-system)
+ (coding-system-for-write mm-binary-coding-system))
+ (set-buffer-multibyte nil)
+ ,@forms)
+ (set-buffer-multibyte ,multibyte))))))
+(put 'mm-with-unibyte-current-buffer 'lisp-indent-function 0)
+(put 'mm-with-unibyte-current-buffer 'edebug-form-spec '(body))
+
(defun mm-find-charset-region (b e)
"Return a list of charsets in the region."
(cond
(charset (mail-content-type-get
(mm-handle-type handle) 'charset))
gnus-displaying-mime handles)
+ (when (and charset
+ (stringp charset))
+ (setq charset (intern (downcase charset)))
+ (when (eq charset 'us-ascii)
+ (setq charset nil)))
(save-excursion
(save-restriction
(narrow-to-region b b)
(mm-insert-part handle)
(let (gnus-article-mime-handles
- (gnus-newsgroup-charset (or charset gnus-newsgroup-charset)))
+ (gnus-newsgroup-charset
+ (or charset gnus-newsgroup-charset)))
(run-hooks 'gnus-article-decode-hook)
(gnus-article-prepare-display)
(setq handles gnus-article-mime-handles))
(delete-region (+ (match-beginning 0) 2)
(+ (match-beginning 0) 3))))))
(setq charset (mm-encode-body))
- (setq encoding (mm-body-encoding charset))
+ (setq encoding (mm-body-encoding charset
+ (cdr (assq 'encoding cont))))
(setq coded (buffer-string)))
(mm-with-unibyte-buffer
(cond
(let ((mml-boundary (mml-compute-boundary cont)))
(insert (format "Content-Type: multipart/%s; boundary=\"%s\"\n"
type mml-boundary))
- (insert "\n")
(setq cont (cddr cont))
(while cont
(insert "\n--" mml-boundary "\n")
(when (string-match "[\"\\~/* \t\n]" value)
(setq value (prin1-to-string value)))
(insert (format " %s=%s" key value)))))
- (insert ">\n<#/" name ">\n"))
+ (insert ">\n"))
+
+(defun mml-insert-empty-tag (name &rest plist)
+ "Insert an empty MML tag described by NAME and PLIST."
+ (when (symbolp name)
+ (setq name (symbol-name name)))
+ (apply #'mml-insert-tag name plist)
+ (insert "<#/" name ">\n"))
;;; Attachment functions.
(type (mml-minibuffer-read-type file))
(description (mml-minibuffer-read-description)))
(list file type description)))
- (mml-insert-tag 'part 'type type 'filename file 'disposition "attachment"
- 'description description))
+ (mml-insert-empty-tag 'part 'type type 'filename file
+ 'disposition "attachment" 'description description))
(defun mml-attach-buffer (buffer &optional type description)
"Attach a buffer to the outgoing MIME message.
(type (mml-minibuffer-read-type buffer "text/plain"))
(description (mml-minibuffer-read-description)))
(list buffer type description)))
- (mml-insert-tag 'part 'type type 'buffer buffer 'disposition "attachment"
- 'description description))
+ (mml-insert-empty-tag 'part 'type type 'buffer buffer
+ 'disposition "attachment" 'description description))
(defun mml-attach-external (file &optional type description)
"Attach an external file into the buffer.
(type (mml-minibuffer-read-type file))
(description (mml-minibuffer-read-description)))
(list file type description)))
- (mml-insert-tag 'external 'type type 'name file 'disposition "attachment"
- 'description description))
+ (mml-insert-empty-tag 'external 'type type 'name file
+ 'disposition "attachment" 'description description))
(defun mml-insert-multipart (&optional type)
(interactive (list (completing-read "Multipart type (default mixed): "
nil nil "mixed")))
(or type
(setq type "mixed"))
- (mml-insert-tag "multipart" 'type type)
+ (mml-insert-empty-tag "multipart" 'type type)
(forward-line -1))
(defun mml-preview (&optional raw)
(if (numberp article)
(cons nnfolder-current-group article)
(goto-char (point-min))
- (search-forward (concat "\n" nnfolder-article-marker))
(cons nnfolder-current-group
- (string-to-int
- (buffer-substring
- (point) (progn (end-of-line) (point)))))))))))
+ (if (search-forward (concat "\n" nnfolder-article-marker)
+ nil t)
+ (string-to-int
+ (buffer-substring
+ (point) (progn (end-of-line) (point))))
+ -1))))))))
(deffoo nnfolder-request-group (group &optional server dont-check)
(nnfolder-possibly-change-group group server t)
(defvoo nnmh-status-string "")
(defvoo nnmh-group-alist nil)
-(defvoo nnmh-allow-delete-final nil)
+(defvar nnmh-allow-delete-final nil)
\f
(deffoo nnslashdot-retrieve-headers (articles &optional group server fetch-old)
(nnslashdot-possibly-change-server group server)
- (unless gnus-nov-is-evil
- (if nnslashdot-threaded
- (nnslashdot-threaded-retrieve-headers articles group)
- (nnslashdot-sane-retrieve-headers articles group))))
+ (condition-case why
+ (unless gnus-nov-is-evil
+ (if nnslashdot-threaded
+ (nnslashdot-threaded-retrieve-headers articles group)
+ (nnslashdot-sane-retrieve-headers articles group)))
+ (search-failed (nnslashdot-lose why))))
(deffoo nnslashdot-threaded-retrieve-headers (articles group)
(let ((last (car (last articles)))
(deffoo nnslashdot-request-article (article &optional group server buffer)
(nnslashdot-possibly-change-server group server)
(let (contents)
- (save-excursion
- (set-buffer nnslashdot-buffer)
- (let ((case-fold-search t))
- (goto-char (point-min))
- (when (and (stringp article)
- (string-match "%\\([0-9]+\\)@" article))
- (setq article (string-to-number (match-string 1 article))))
- (when (numberp article)
- (if (= article 1)
- (progn
- (re-search-forward "Posted by .* on ")
- (forward-line 1)
+ (condition-case why
+ (save-excursion
+ (set-buffer nnslashdot-buffer)
+ (let ((case-fold-search t))
+ (goto-char (point-min))
+ (when (and (stringp article)
+ (string-match "%\\([0-9]+\\)@" article))
+ (setq article (string-to-number (match-string 1 article))))
+ (when (numberp article)
+ (if (= article 1)
+ (progn
+ (re-search-forward "Posted by .* on ")
+ (forward-line 1)
+ (setq contents
+ (buffer-substring
+ (point)
+ (progn
+ (re-search-forward
+ "<p>.*A href=http://slashdot.org/article.pl")
+ (match-beginning 0)))))
+ (search-forward (format "<a name=\"%d\">" (1- article)))
(setq contents
(buffer-substring
- (point)
- (progn
- (re-search-forward
- "<p>.*A href=http://slashdot.org/article.pl")
- (match-beginning 0)))))
- (search-forward (format "<a name=\"%d\">" (1- article)))
- (setq contents
- (buffer-substring
- (re-search-forward "<td[^>]+>")
- (search-forward "</td>")))))))
+ (re-search-forward "<td[^>]+>")
+ (search-forward "</td>")))))))
+ (search-failed (nnslashdot-lose why)))
+
(when contents
(save-excursion
(set-buffer (or buffer nntp-server-buffer))
(nnslashdot-possibly-change-server nil server)
(let ((number 0)
sid elem description articles gname)
- ;; First we do the Ultramode to get info on all the latest groups.
- (with-temp-buffer
- (nnweb-insert "http://slashdot.org/slashdot.xml")
- (goto-char (point-min))
- (while (search-forward "<story>" nil t)
- (narrow-to-region (point) (search-forward "</story>"))
- (goto-char (point-min))
- (re-search-forward "<title>\\([^<]+\\)</title>")
- (setq description (match-string 1))
- (re-search-forward "<url>\\([^<]+\\)</url>")
- (setq sid (match-string 1))
- (string-match "/\\([0-9/]+\\).shtml" sid)
- (setq sid (match-string 1 sid))
- (re-search-forward "<comments>\\([^<]+\\)</comments>")
- (setq articles (string-to-number (match-string 1)))
- (setq gname (concat description " (" sid ")"))
- (if (setq elem (assoc gname nnslashdot-groups))
- (setcar (cdr elem) articles)
- (push (list gname articles sid) nnslashdot-groups))
- (goto-char (point-max))
- (widen)))
- ;; Then do the older groups.
- (while (> (- nnslashdot-group-number number) 0)
- (with-temp-buffer
- (let ((case-fold-search t))
- (nnweb-insert (format nnslashdot-active-url number))
- (goto-char (point-min))
- (while (re-search-forward
- "article.pl\\?sid=\\([^&]+\\).*<b>\\([^<]+\\)</b>" nil t)
- (setq sid (match-string 1)
- description (match-string 2))
- (forward-line 1)
- (when (re-search-forward "<b>\\([0-9]+\\)</b>" nil t)
- (setq articles (string-to-number (match-string 1))))
- (setq gname (concat description " (" sid ")"))
- (if (setq elem (assoc gname nnslashdot-groups))
- (setcar (cdr elem) articles)
- (push (list gname articles sid) nnslashdot-groups)))))
- (incf number 30))
+ (condition-case why
+ ;; First we do the Ultramode to get info on all the latest groups.
+ (mm-with-unibyte-buffer
+ (nnweb-insert "http://slashdot.org/slashdot.xml")
+ (goto-char (point-min))
+ (while (search-forward "<story>" nil t)
+ (narrow-to-region (point) (search-forward "</story>"))
+ (goto-char (point-min))
+ (re-search-forward "<title>\\([^<]+\\)</title>")
+ (setq description (match-string 1))
+ (re-search-forward "<url>\\([^<]+\\)</url>")
+ (setq sid (match-string 1))
+ (string-match "/\\([0-9/]+\\).shtml" sid)
+ (setq sid (match-string 1 sid))
+ (re-search-forward "<comments>\\([^<]+\\)</comments>")
+ (setq articles (string-to-number (match-string 1)))
+ (setq gname (concat description " (" sid ")"))
+ (if (setq elem (assoc gname nnslashdot-groups))
+ (setcar (cdr elem) articles)
+ (push (list gname articles sid) nnslashdot-groups))
+ (goto-char (point-max))
+ (widen)))
+ ;; Then do the older groups.
+ (while (> (- nnslashdot-group-number number) 0)
+ (mm-with-unibyte-buffer
+ (let ((case-fold-search t))
+ (nnweb-insert (format nnslashdot-active-url number))
+ (goto-char (point-min))
+ (while (re-search-forward
+ "article.pl\\?sid=\\([^&]+\\).*<b>\\([^<]+\\)</b>" nil t)
+ (setq sid (match-string 1)
+ description (match-string 2))
+ (forward-line 1)
+ (when (re-search-forward "<b>\\([0-9]+\\)</b>" nil t)
+ (setq articles (string-to-number (match-string 1))))
+ (setq gname (concat description " (" sid ")"))
+ (if (setq elem (assoc gname nnslashdot-groups))
+ (setcar (cdr elem) articles)
+ (push (list gname articles sid) nnslashdot-groups)))))
+ (incf number 30))
+ (search-failed (nnslashdot-lose why)))
(nnslashdot-write-groups)
(nnslashdot-generate-active)
t))
-
+
(deffoo nnslashdot-request-newgroups (date &optional server)
(nnslashdot-possibly-change-server nil server)
(nnslashdot-generate-active)
(insert "</blockquote>\n")
(setq quoted nil)))
(forward-line 1))
+ (goto-char (point-min))
+ (while (re-search-forward "^ *\n" nil t)
+ (replace-match "<p>\n"))
(widen)
(when (message-goto-signature)
(forward-line -1)
(defun nnslashdot-read-groups ()
(let ((file (expand-file-name "groups" nnslashdot-directory)))
(when (file-exists-p file)
- (with-temp-buffer
+ (mm-with-unibyte-buffer
(insert-file-contents file)
(goto-char (point-min))
(setq nnslashdot-groups (read (current-buffer)))))))
(insert (prin1-to-string (car elem))
" " (number-to-string (cadr elem)) " 1 y\n"))))
+(defun nnslashdot-lose (why)
+ (error "Slashdot HTML has changed; please get a new version of nnslashdot"))
+
(provide 'nnslashdot)
;;; nnslashdot.el ends here
(received 0)
(last-point (point-min))
(nntp-inhibit-erase t)
+ (buf (nntp-find-connection-buffer nntp-server-buffer))
(command (if nntp-server-list-active-group "LIST ACTIVE" "GROUP")))
(while groups
;; Send the command to the server.
(zerop (% count nntp-maximum-request)))
(nntp-accept-response)
(while (progn
+ ;; Search `blue moon' in this file for the
+ ;; reason why set-buffer here.
+ (set-buffer buf)
(goto-char last-point)
;; Count replies.
(while (re-search-forward "^[0-9]" nil t)
(nntp-accept-response))))
;; Wait for the reply from the final command.
+ (set-buffer buf)
(goto-char (point-max))
(re-search-backward "^[0-9]" nil t)
(when (looking-at "^[23]")
(while (progn
+ (set-buffer buf)
(goto-char (point-max))
(if (not nntp-server-list-active-group)
(not (re-search-backward "\r?\n" (- (point) 3) t))
(nntp-accept-response)))
;; Now all replies are received. We remove CRs.
+ (set-buffer buf)
(goto-char (point-min))
(while (search-forward "\r" nil t)
(replace-match "" t t))
(set-buffer nntp-server-buffer)
(erase-buffer))
(setq nnultimate-articles nil)
- (with-temp-buffer
+ (mm-with-unibyte-buffer
(dolist (elem fetchers)
(setq pages 1
current-page 1
(setq nnultimate-headers (sort headers 'car-less-than-car))
(save-excursion
(set-buffer nntp-server-buffer)
- (erase-buffer)
- (dolist (header nnultimate-headers)
- (nnheader-insert-nov (cdr header)))))
+ (mm-with-unibyte-current-buffer
+ (erase-buffer)
+ (dolist (header nnultimate-headers)
+ (nnheader-insert-nov (cdr header))))))
'nov)))
(deffoo nnultimate-request-group (group &optional server dont-check)
(goto-char (point-min))
(insert "Content-Type: text/html\nMIME-Version: 1.0\n")
(let ((header (cdr (assq article nnultimate-headers))))
- (nnheader-insert-header header))
+ (mm-with-unibyte-current-buffer
+ (nnheader-insert-header header)))
(nnheader-report 'nnultimate "Fetched article %s" article)
(cons group article)))))
(deffoo nnultimate-request-list (&optional server)
(nnultimate-possibly-change-server nil server)
- (with-temp-buffer
+ (mm-with-unibyte-buffer
(nnweb-insert
(if (string-match "/$" nnultimate-address)
(concat nnultimate-address "Ultimate.cgi")
(furls (list (concat nnultimate-address (format furl sid))))
contents forum-contents furl-fetched a subject href
garticles topic tinfo old-max inc parse)
- (with-temp-buffer
+ (mm-with-unibyte-buffer
(while furls
(erase-buffer)
(nnweb-insert (pop furls))
(setq nnultimate-groups-alist nil)
(let ((file (expand-file-name "groups" nnultimate-directory)))
(when (file-exists-p file)
- (with-temp-buffer
+ (mm-with-unibyte-buffer
(insert-file-contents file)
(goto-char (point-min))
(setq nnultimate-groups-alist (read (current-buffer)))))))
(set-buffer nntp-server-buffer)
(erase-buffer)
(let (article header)
- (while (setq article (pop articles))
- (when (setq header (cadr (assq article nnweb-articles)))
- (nnheader-insert-nov header)))
+ (mm-with-unibyte-current-buffer
+ (while (setq article (pop articles))
+ (when (setq header (cadr (assq article nnweb-articles)))
+ (nnheader-insert-nov header))))
'nov)))
(deffoo nnweb-request-scan (&optional group server)
(let* ((header (cadr (assq article nnweb-articles)))
(url (and header (mail-header-xref header))))
(when (or (and url
- (nnweb-fetch-url url))
+ (mm-with-unibyte-current-buffer
+ (nnweb-fetch-url url)))
(and (stringp article)
(nnweb-definition 'id t)
(let ((fetch (nnweb-definition 'id))
(setq art (match-string 1 article)))
(and fetch
art
- (nnweb-fetch-url
- (format fetch article))))))
+ (mm-with-unibyte-current-buffer
+ (nnweb-fetch-url
+ (format fetch article)))))))
(unless nnheader-callback-function
(funcall (nnweb-definition 'article))
(nnweb-decode-entities))
(defun nnweb-read-overview (group)
"Read the overview of GROUP and build the map."
(when (file-exists-p (nnweb-overview-file group))
- (with-temp-buffer
+ (mm-with-unibyte-buffer
(nnheader-insert-file-contents (nnweb-overview-file group))
(goto-char (point-min))
(let (header)
(unless (gnus-buffer-live-p nnweb-buffer)
(setq nnweb-buffer
(save-excursion
- (nnheader-set-temp-buffer
- (format " *nnweb %s %s %s*" nnweb-type nnweb-search server))))))
+ (let ((multibyte (default-value 'enable-multibyte-characters)))
+ (unwind-protect
+ (progn
+ (setq-default enable-multibyte-characters nil)
+ (nnheader-set-temp-buffer
+ (format " *nnweb %s %s %s*"
+ nnweb-type nnweb-search server)))
+ (setq-default enable-multibyte-characters multibyte))
+ (current-buffer))))))
(defun nnweb-fetch-url (url)
- (save-excursion
- (if (not nnheader-callback-function)
- (let ((buf (current-buffer)))
- (save-excursion
- (set-buffer nnweb-buffer)
+ (let (buf)
+ (save-excursion
+ (if (not nnheader-callback-function)
+ (progn
+ (with-temp-buffer
+ (mm-enable-multibyte)
+ (let ((coding-system-for-read 'binary)
+ (coding-system-for-write 'binary)
+ (default-process-coding-system 'binary))
+ (nnweb-insert url))
+ (setq buf (buffer-string)))
(erase-buffer)
- (url-insert-file-contents url)
- (copy-to-buffer buf (point-min) (point-max))
- t))
- (nnweb-url-retrieve-asynch
- url 'nnweb-callback (current-buffer) nnheader-callback-function)
- t)))
+ (insert buf)
+ t)
+ (nnweb-url-retrieve-asynch
+ url 'nnweb-callback (current-buffer) nnheader-callback-function)
+ t))))
(defun nnweb-callback (buffer callback)
(when (gnus-buffer-live-p url-working-buffer)
(dolist (row (nth 2 (car (nth 2 table))))
(setq a (nnweb-parse-find 'a row)
url (cdr (assq 'href (nth 1 a)))
- text (nnweb-text row))
+ text (nreverse (nnweb-text row)))
(when a
- (setq subject (nth 2 text)
- group (nth 4 text)
- date (nth 5 text)
- from (nth 6 text))
- (string-match "\\([0-9]+\\)/\\([0-9]+\\)/\\([0-9]+\\)" date)
- (setq date (format "%s %s %s"
- (car (rassq (string-to-number
- (match-string 2 date))
- parse-time-months))
- (match-string 3 date) (match-string 1 date)))
+ (setq subject (nth 4 text)
+ group (nth 2 text)
+ date (nth 1 text)
+ from (nth 0 text))
+ (if (string-match "\\([0-9]+\\)/\\([0-9]+\\)/\\([0-9]+\\)" date)
+ (setq date (format "%s %s 00:00:00 %s"
+ (car (rassq (string-to-number
+ (match-string 2 date))
+ parse-time-months))
+ (match-string 3 date)
+ (match-string 1 date)))
+ (setq date "Jan 1 00:00:00 0000"))
(incf i)
(setq url (concat url "&fmt=text"))
(unless (nnweb-get-hashtb url)
If your Emacs implementation can't decode CHARSET, it returns nil."
(if (stringp charset)
(setq charset (intern (downcase charset))))
- (if (or (not charset) (memq charset mail-parse-ignored-charsets))
+ (if (or (not charset)
+ (eq 'gnus-all mail-parse-ignored-charsets)
+ (memq 'gnus-all mail-parse-ignored-charsets)
+ (memq charset mail-parse-ignored-charsets))
(setq charset mail-parse-charset))
(let ((cs (mm-charset-to-coding-system charset)))
+ (if (and (not cs) charset
+ (listp mail-parse-ignored-charsets)
+ (memq 'gnus-unknown mail-parse-ignored-charsets))
+ (setq cs (mm-charset-to-coding-system mail-parse-charset)))
(when cs
(when (and (eq cs 'ascii)
mail-parse-charset)
+1999-12-03 00:02:11 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * gnus.texi (Other Gnus Versions): New.
+ (Gnus Versions): Made into own node.
+
+1999-12-02 00:00:00 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * gnus.texi (Paging the Article): Addition.
+ (History): Addition.
+
+1999-11-24 Carsten Leonhardt <leo@arioch.oche.de>
+
+ * gnus.texi (Mail Source Specifiers): Mention maildir in the
+ overview and the possibility to use remote maildirs.
+
1999-12-01 14:21:19 Lars Magne Ingebrigtsen <larsi@gnus.org>
* gnus.texi (Topic Parameters): Addition.
(Summary Message Commands): New.
(Canceling and Superseding): Made into subsection.
+ (Charsets): Addition.
1999-11-30 10:54:31 Shenghuo ZHU <zsh@cs.rochester.edu>
\input texinfo @c -*-texinfo-*- -*- coding: iso-latin-1 -*-
@setfilename gnus
-@settitle Pterodactyl Gnus Manual
+@settitle Gnus Manual
@synindex fn cp
@synindex vr cp
@synindex pg cp
@tex
@titlepage
-@title Pterodactyl Gnus Manual
+@title Gnus Manual
@author by Lars Magne Ingebrigtsen
@page
spool or your mbox file. All at the same time, if you want to push your
luck.
-This manual corresponds to Pterodactyl Gnus .
+This manual corresponds to Gnus 5.8.2.
@end ifinfo
@kindex A g (Summary)
@kindex g (Summary)
@findex gnus-summary-show-article
+@vindex gnus-summary-show-article-charset-alist
(Re)fetch the current article (@code{gnus-summary-show-article}). If
given a prefix, fetch the current article, but don't run any of the
article treatment functions. This will give you a ``raw'' article, just
the way it came from the server.
+If given a numerical prefix, you can do semi-manual charset stuff.
+@kbd{C-u 0 g cn-gb-2312 RET} will decode the message as if it were
+encoded in the @code{cn-gb-2312} charset. If you have
+
+@lisp
+(setq gnus-summary-show-article-charset-alist
+ '((1 . cn-gb-2312)
+ (2 . big5)))
+@end lisp
+
+then you can say @kbd{C-u 1 g} to get the same effect.
+
@item A <
@itemx <
@kindex < (Summary)
@table @kbd
@item b
-@itemx K b
+@itemx K v
@kindex b (Summary)
-@kindex K b (Summary)
+@kindex K v (Summary)
View the @sc{mime} part.
@item K o
Parameters}). The default value is @code{(unknown-8bit)}, which is
something some agents insist on having in there.
+@cindex Russina
+@cindex koi8-r
+@cindex koi8-u
+@cindex iso-8859-5
+@cindex coding system aliases
+@cindex preferred charset
+
+Other charset tricks that may be useful, although not Gnus-specific:
+
+If there are several @sc{mime} charsets that encode the same Emacs
+charset, you can choose what charset to use by saying the following:
+
+@lisp
+(put-charset-property 'cyrillic-iso8859-5
+ 'preferred-coding-system 'koi8-r)
+@end lisp
+
+This means that Russian will be encoded using @code{koi8-r} instead of
+the default @code{iso-8859-5} @sc{mime} charset.
+
+If you want to read messages in @code{koi8-u}, you can cheat and say
+
+@lisp
+(define-coding-system-alias 'koi8-u 'koi8-r)
+@end lisp
+
+This will almost do the right thing.
+
+And finally, to read charsets like @code{windows-1251}, you can say
+something like
+
+@lisp
+(codepage-setup 1251)
+(define-coding-system-alias 'windows-1251 'cp1251)
+@end lisp
+
@node Article Commands
@section Article Commands
@subsection Mail Sources
Mail can be gotten from many different sources---the mail spool, from a
-POP mail server, or from a procmail directory, for instance.
+POP mail server, from a procmail directory, or from a maildir, for
+instance.
@menu
* Mail Source Specifiers:: How to specify what a mail source is.
@end lisp
@item maildir
-Get mail from a maildir. This is a type of mailbox currently only
-supported by qmail, where each file in a special directory contains
-exactly one mail.
+Get mail from a maildir. This is a type of mailbox that is supported by
+at least qmail and postfix, where each file in a special directory
+contains exactly one mail.
Keywords:
If you sometimes look at your mail through a pop3 daemon before fetching
them with Gnus, you may also have to fetch your mails from the
-@code{cur} directory inside the maildir, like in the following example.
+@code{cur} directory inside the maildir, like in the first example
+below.
+
+You can also get mails from remote hosts (because maildirs don't suffer
+from locking problems).
@end table
-An example maildir mail source:
+Two example maildir mail sources:
@lisp
(maildir :path "/home/user-name/Maildir/cur")
@end lisp
+@lisp
+(maildir :path "/user@@remotehost.org:~/Maildir/new")
+@end lisp
+
@item imap
Get mail from a @sc{imap} server. If you don't want to use @sc{imap} as intended,
as a network mail reading protocol (ie with nnimap), for some reason or
renamed it back again to ``Gnus''. But in mixed case. ``Gnus'' vs.
``@sc{gnus}''. New vs. old.
+@menu
+* Gnus Versions:: What Gnus versions have been released.
+* Other Gnus Versions:: Other Gnus versions that also have been released.
+* Why?:: What's the point of Gnus?
+* Compatibility:: Just how compatible is Gnus with @sc{gnus}?
+* Conformity:: Gnus tries to conform to all standards.
+* Emacsen:: Gnus can be run on a few modern Emacsen.
+* Gnus Development:: How Gnus is developed.
+* Contributors:: Oodles of people.
+* New Features:: Pointers to some of the new stuff in Gnus.
+* Newest Features:: Features so new that they haven't been written yet.
+@end menu
+
+
+@node Gnus Versions
+@subsection Gnus Versions
+@cindex Pterodactyl Gnus
+@cindex ding Gnus
+@cindex September Gnus
+@cindex Quassia Gnus
+
The first ``proper'' release of Gnus 5 was done in November 1995 when it
was included in the Emacs 19.30 distribution (132 (ding) Gnus releases
plus 15 Gnus 5.0 releases).
On July 28th 1996 work on Red Gnus was begun, and it was released on
January 25th 1997 (after 84 releases) as ``Gnus 5.4'' (67 releases).
-On September 13th 1997, Quassia Gnus was started and lasted 37
-releases. If was released as ``Gnus 5.6 on March 8th 1998.
+On September 13th 1997, Quassia Gnus was started and lasted 37 releases.
+If was released as ``Gnus 5.6'' on March 8th 1998 (46 releases).
+
+Gnus 5.6 begat Pterodactyl Gnus on August 29th 1998 and was released as
+``Gnus 5.8'' (after 99 releases and a CVS repository) on December 3rd
+1999.
If you happen upon a version of Gnus that has a prefixed name --
``(ding) Gnus'', ``September Gnus'', ``Red Gnus'', ``Quassia Gnus'' --
out of its reach. Find a proper released version of Gnus and snuggle up
to that instead.
-@menu
-* Why?:: What's the point of Gnus?
-* Compatibility:: Just how compatible is Gnus with @sc{gnus}?
-* Conformity:: Gnus tries to conform to all standards.
-* Emacsen:: Gnus can be run on a few modern Emacsen.
-* Gnus Development:: How Gnus is developed.
-* Contributors:: Oodles of people.
-* New Features:: Pointers to some of the new stuff in Gnus.
-* Newest Features:: Features so new that they haven't been written yet.
-@end menu
+
+@node Other Gnus Versions
+@subsection Other Gnus Versions
+@cindex Semi-gnus
+
+In addition to the versions of Gnus which have had their releases
+coordinated by Lars, one major development has been Semi-gnus from
+Japan. It's based on a library called @sc{semi}, which provides
+@sc{mime} capabilities.
+
+These Gnusae are based mainly on Gnus 5.6 and Pterodactyl Gnus.
+Collectively, they are called ``Semi-gnus'', and different strains are
+called T-gnus, ET-gnus, Nana-gnus and Chaos. These provide powerful
+@sc{mime} and multilingualization things, especially important for
+Japanese users.
@node Why?
Be able to forward groups of messages as MIME digests.
@item
+nnweb should include the "get whole article" article when getting articles.
+
+@item
Solve the halting problem.
@c TODO
--- /dev/null
+@node Mail with Gnus, , Key bindings, Top
+@comment node-name, next, previous, up
+@chapter Mail with Gnus
+
+Quite a few people wish to read mail with Gnus but stumble across a few
+issues which make this a bit difficult. This comes from the fact that
+Gnus is really a newsreader, and thus it treats mail in a newsreaderly
+fashion. It is not desirable to change this, because it is a wonderful
+thing and this is what distinguishes Gnus from other mail readers. In
+this little tutorial, I'll try to explain what ``newsreaderly fashion''
+means and how exactly Gnus treats mail.
+
+Specific pieces of behavior can always be changed, but if you desire to
+make Gnus behave like a conventional mail reader, think again. It will
+be an uphill battle. Maybe a different mail reader is for you? But
+also, read on. Maybe you'll find the right behavior in the description
+below.
+
+@c ------------------------------------------------------------
+@section Gnus Terminology
+@c ------------------------------------------------------------
+
+First, let's talk about a few terms which I'm going to use which might
+be unfamiliar to you.
+
+@table @dfn
+@item Posting, Article, Message, Mail
+These are all related terms. A news message might also be called a
+posting or an article, whereas a mail message is known as a mail. Since
+Gnus treats both news and mail, the distinction isn't as clear. In the
+following, I'll use the term ``message'' for the generic case and ``news
+message'' and ``mail message'' for the specific cases. But sometimes, I
+might use ``posting'' or ``article'', too, both synonymous with
+``message''.
+
+@item Backend
+Gnus can read messages from various sources. On the one hand, there is
+news, and on the other hand, there is mail. News can be read from a
+news server (an NNTP server), or from a so-called spool directory. Mail
+can be read in various formats.
+
+Generally speaking, a backend describes the way Gnus accesses a set of
+messages. For a news server, this is the Network News Transfer
+Protocol, NNTP, and thus there is a backend ``nntp''. For mail stored
+in the same format that the MH message handling system used, there is
+the backend ``nnmh''. And so on. See below for a list of backends.
+
+@item Server
+Whereas a backend describes the mechanism used by Gnus to access the
+messages, a server is a specific instance of that mechanism. You might
+create a specific server for accessing the host @file{news.frob.org}
+using NNTP, say. Or you might create a server for accessing the
+MH-style directory @file{~/OldMail}.
+
+If you are a programmer, think of a backend as the class and of a server
+as an object (instance) of that class. If you are a cook, think of a
+backend as an apple pie recipe (say), and think of a server as an actual
+apple pie. (Yummy!) If you live in a huge city, think of a backend as
+a bus (or tram, or underground) line (the Circle Line comes to mind),
+and think of a server as a specific bus (or tram train, or underground
+train). The one at 8:15 last Monday morning, for example. If you drive
+a car, think of a backend as the model and make and of a server as a
+specific car.
+
+Obviously, there can be two servers using the same backend. (Two
+instances of the same class, two apple pies baked according to the same
+recipe, two busses going the same route, two cars of the same model.)
+
+@item (Select) method
+Just another term for server.
+
+@item Native server
+This is the primary server, so to speak. Most people let their news
+server be the native server, hence:
+@lisp
+(setq gnus-select-method '(nntp "news.frob.org"))
+@end lisp
+Groups from the native server are also known as native groups.
+
+@item Secondary select methods
+This is a list of other servers which one also wishes to use. Many
+people are only going to have two servers, one native (for news) and one
+secondary (for mail). Thus:
+@lisp
+(setq gnus-secondary-select-methods '((nnml "")))
+@end lisp
+Note that there is one more pair of parentheses in order to be able to
+mention more than one seconary select method.
+
+Groups from a secondary server are also known as secondary groups.
+
+In order to be able to distinguish native groups from secondary groups,
+each server is identified with a (unique) name and that name is used as
+a prefix for the secondary groups. Thus, you might have a group
+@file{gnu.emacs.help} (which is native) and another group
+@file{nnml:mail.misc} (which is secondary). A plus character is used if
+the name of a server is not the empty string. For example, given the
+following in your @file{.gnus} file
+@lisp
+(setq gnus-secondary-select-methods
+ '((nnml "work" (nnml-directory "~/Mail.work/"))
+ (nnml "play" (nnml-directory "~/Mail.play/"))))
+@end lisp
+you might have the groups @file{nnml+work:boss} and
+@file{nnml+play:so}@footnote{``SO'' standing for ``significant other'',
+i.e.@ girlfriend or boyfriend}.
+
+@item Group
+Well, if you've read news before, you know about different news groups.
+One of my favorites is @file{gnu.emacs.gnus}, and I wish I would read
+@file{alt.fan.pratchett}. Since Gnus treats mail in a newsreaderly
+fashion, it is obvious that it uses groups rather than ``folders'' like
+other mail readers do. So with Gnus there are news groups and mail
+groups, where mail groups are known as mail folders to other programs.
+
+Each group belongs to a certain server, and each server uses a certain
+backend.
+
+@item Expiry
+News servers offer news groups which contain news postings. New news
+postings come in, so the news postings accumulate, and pretty soon the
+new hard disk is full. This is not good news at all.
+
+Thus, a news server does what is known as @dfn{expiry}: it deletes old
+messages. Of course, on a news server, expiry happens with no regard of
+whether people have already seen the message in question; instead, the
+news server admin chooses expiry times based on available disk space and
+maybe on the normal amount of traffic in a news group.
+
+But mail messages should be under the users' control, so there better be
+no server which deletes messages regardless of users having seen them!
+Instead, Gnus adopts a scheme where users say which messages may be
+deleted, and Gnus takes care of deleting them after a while. (They are
+not deleted immediately in case you made a mistake, or in case you wish
+to refer back to an old article.)
+
+@item Article marks
+Gnus distinguishes between a number of article marks, which indicate
+whether they have been looked at, or are considered important, or the
+like. Marks are represented by a character.
+
+If that character is a space, it looks as if the message isn't marked at
+all. These messages are called @dfn{unmarked}, the mark character used
+is a space, and marking a message with space is considered to be the
+same as removing all marks---after all, such messages are unmarked. You
+can type @kbd{M-u} to remove all marks and make an article unmarked.
+
+Articles that are considered important or where you wish to indicate
+that you have to deal with them later can be @dfn{ticked}. The mark
+character used for ticked messages is the exclamation mark, and you can
+use @kbd{u} or @kbd{!} to tick messages. Ticked messages are always
+shown when you enter a group.
+
+There is the @dfn{dormant} mark which is similar to the ticked mark but
+does not imply importance or urgency; thus, dormant messages aren't
+shown by default. The mark character used is the question mark, and you
+can mark messages as dormant using the @kbd{?} key.
+
+So far, each kind of mark was associated with one character (as was the
+absence of any mark). But articles which you have read are a bit
+different, since lots of different characters are used here. The
+important thing to realize is that these messages are treated in the
+same way by Gnus; the different characters are only used as an
+information for the user.
+
+Articles which are marked as read because you have actually read them
+(the normal case, one would think) are marked with the `R' character.
+(Type @kbd{@key{SPC}} or @kbd{g} to read a message, or click on it using
+the middle mouse button, @kbd{@key{mouse-2}}.) You can also mark a
+message as read without actually reading it, this is indicated with the
+`r' character and can be achieved with @kbd{d} or @kbd{M r}.
+
+After exiting a group and then entering it again (some time later), the
+messages that had been marked as read before appear with the `O'
+character.
+
+To reiterate: the difference between `r', `R' and `O' is only an
+information for the user.
+
+@end table
+
+
+
+@c ------------------------------------------------------------
+@section Choosing a mail backend
+@c ------------------------------------------------------------
+
+The Gnus manual lists quite a few backends. Of these, the news backends
+pose no problem: you use the @code{nntp} backend if you access a news
+server and the @code{nnspool} backend if you have a local news spool
+directory. (Leafnode users should use @code{nntp} so that the leafnode
+program can see what you are doing and choose the groups to download
+accordingly.) But the mail backends are more difficult. There are many
+of them, and it is not obvious which is the best choice. In quite a few
+cases, this is because there is no single best choice; or maybe what's
+the best choice depends on the group or changes over time.
+
+Below, I'll give a list of mail backends. While I say something about
+how messages are stored, I'll try to emphasize what that means for you
+as a user.
+
+Let's try to structure the discussion a bit. We have servers, which
+contain groups, which in turn contain messages. How could we store this
+on disk? After some thought, you'll quickly come up with the following
+alternatives: You could store all messages from a server in one file.
+The second alternative is to store all messages from one group in one
+file, different groups are stored in different files. A third
+alternative is to store each message in one file; in this case, one
+could use a directory per group. A very interesting fourth alternative
+is not to store the messages at all but instead to use the Oracle of
+Delphi (say) to predict what the messages will be; this saves a lot of
+disk space. I won't talk about the fourth alternative in the following.
+
+
+@subsection Backends with one file per server
+
+Many people use just two servers, the native server for news and a
+secondary server for mail. Thus, this alternative would mean that you
+store all your mail in one file. Since Emacs has no fancy mechanisms to
+access parts of files, this means that Gnus loads that file into main
+memory at startup, and all your mails are kept in main memory all the
+time. (Of course, copies are written to disk every now and then, for
+safekeeping!)
+
+I think you can pretty much figure out the consequences on your own,
+now:
+@itemize @bullet
+@item
+Handling large amounts of mail will be a problem. (Emacs has a maximum
+file size of 128 MB.)
+
+@item
+Some operations on mails will be fast, since they are in-memory
+operations. (Saving everything to disk will be slow, though.)
+
+@item
+Some operations on mails will be slow, since they have to search through
+the whole file.
+
+@item
+It is convenient to have all mail stored in one file: you can easily
+transfer it to another computer using FTP, say, or store it on a floppy
+or Zip disk or a tape.
+
+@end itemize
+
+Conclusion: If you don't have a lot of mail to deal with and like the
+convenience of storing it all in one file, one of these backends might
+be for you. However, since Gnus really shines when dealing with lots of
+mails, most Gnus users can be expected to deal with quite a large volume
+of mail. Thus, I don't think many Gnus users choose one of these
+backends.
+
+@table @code
+@item nnmbox
+This backend uses the well-known ``mbox'' format for storing mails. In
+this format, a message begins with the five characters @code{From_} (the
+last character is a space) at the beginning of a line, and ends with an
+empty line.
+
+@item nnbabyl
+This backend uses the lesser known ``babyl'' format for storing mails.
+This uses delimiters for the beginning and the end of a message which
+are less likely to occur in a message.
+
+@quotation
+CCC Are they guaranteed to never occur?
+@end quotation
+
+One advantage of a babyl file over an mbox file is that it is possible
+to insert information about a message in the babyl file, without having
+to change the message itself. In an mbox file, the only place to put
+such information is the message header, which is part of the message.
+Thus, adding information about a message to an mbox file means that one
+has to change the message.
+
+I think Gnus doesn't make use of this advantage, though. Gnus stores
+information about messages in an extra file, @file{~/.newsrc.eld}.
+
+@end table
+
+@quotation
+CCC Can somebody provide me with some more arguments in favor of one of
+the formats?
+
+CCC Is it possible to just use an existing babyl file for Gnus, by
+creating a new nnmbox server and pointing it at the file? What about
+mbox?
+@end quotation
+
+
+@subsection Backends with one file per group
+
+Storing all messages in a group in one file provides a nice middle
+ground between the one file per server type of backend and the one file
+per message type of backend. Using lots of little files wastes disk
+space; since this approach uses a moderate number of files, less disk
+space is wasted.
+
+@quotation
+CCC Which operations are fast using this kind of backend? Which are
+slow?
+@end quotation
+
+@table @code
+@item nnfolder
+This backend uses the same file format as @code{nnmbox}, but uses the
+one file per group approach.
+
+@end table
+
+There is no ``nnbabylfolder'' backend which uses babyl format.
+
+
+@subsection Backends with one file per message
+
+If the number of messages grows so large that even the size of a single
+group exceeds the limit which can be handled by the file-per-group
+backends, you need to think about using one of the backends mentioned
+here.
+
+This category also includes @code{nnml}, the backend which is fastest if
+you have lots of messages.
+
+@table @code
+@item nnmh
+This backend uses the same file format (and directory structure) as MH,
+i.e.@ a group is a directory, and each message is stored in a file, and
+the file names are numbers.
+
+Since @code{nnml} is so similar to @code{nnmh} but a lot faster, only
+unusual situations could warrant using this backend. You may want to
+use @code{nnmh} if you wish to use Gnus in parallel to your old MH based
+reader.
+
+Normally, you should not let two programs write the same Gnus directory
+(not even two instances of Gnus!), but if you really must, you may wish
+to use @code{nnmh}, since there the probability of things breaking is
+smaller than with the other backends.
+
+@item nnml
+This backend is like @code{nnmh} but also includes an extra file
+@file{.overview} in each directory (group) which contains some headers
+from each message. Thus, where @code{nnmh} needs to open every file in
+a group to examine its headers, @code{nnml} (normally) needs to only
+read the @file{.overview} file, which is a lot faster.
+@end table
+
+
+@subsection Other mail backends
+
+There is one other mail backend, for keeping messages on an IMAP server.
+
+@table @code
+@item nnimap
+This backend transforms Gnus into an IMAP client. The general idea of
+IMAP is to store and manipulate the mails on a server (similar to NNTP
+for news).
+
+@code{nnimap} only works with the current development version of Gnus,
+though. See @url{http://www.extundo.com/nnimap/} for @code{nnimap} and
+see @url{http://www.gnus.org/} for Gnus. Don't forget to subscribe to
+both the Gnus and the nnimap mailing lists since you are using alpha
+grade software which can be exptected to have bugs. Be prepared to
+submit meaningful bug reports if you encounter bugs.
+
+Rumor has it that @code{nnimap} will be integrated with the next version
+of Gnus (version 5.8, presumably), when that comes out.
+
+@end table
+
+
+@subsection Summary
+
+If you must talk to an IMAP server, the choice is clear. But if you
+keep mails on your local disk, the choice isn't as clear-cut. I think
+that @code{nnml} is generally the best choice unless you have real great
+disk space trouble. Then, you should be thinking about @code{nnfolder}.
+
+I'm not sure if there is a situation where @code{nnmbox} or
+@code{nnbabyl} is desirable.
+
+@quotation
+CCC Tell me about it if you know more!
+@end quotation
+
+
+@c ------------------------------------------------------------
+@section Auto-expire versus total-expire
+@c ------------------------------------------------------------
+
+Every now and then, people ask about auto-expire and total-expire.
+Since both of these features are means to the same end, and since they
+are similar and dissimilar at the same time, great confusion can result
+in the unsuspecting new Gnus user. I'll try to explain how each works
+and which one to use. However, be prepared that there will be no clear
+recommendation: both work well, so for many situations both are
+appropriate. So it is more a matter of taste which one to choose. And
+I can't help you with that!
+
+
+@subsection What is expiry?
+
+Gnus treats mail in a newsreaderly fashion, so it is useful to examine
+the situation for news. Your news server periodically contacts other
+news servers and exchanges messages with the other server. The two news
+servers exchange lists of messages, and messages present in one server
+but not in the other are sent to the other server. This works in both
+directions. Many connections between news servers exist, and this is
+the way how postings travel from you into the world: when you post a
+message, your news server stores it and offers it to the other servers
+in the message list exchanging phase. Since the other servers aren't
+going to have the posting you just wrote, it gets transferred and
+finally can be seen all over the world.
+
+You can quickly see that new messages will be arriving at your news
+server, which stores them on disk. So something has got to happen else
+the disk will fill up real fast. That ``something'' is expiry: the
+oldest messages are deleted to make room for the new ones. Normally, a
+news server can be configured on a per-group basis which messages should
+be deleted. In some groups, messages might be deleted which are older
+than a day, in other groups, messages might be kept for a month.
+
+This means if you go on vacation then come back later to read news, you
+are likely to miss some postings if the expiration time for the groups
+you read is shorter than the time you were on vacation.
+
+How does that apply to mail?
+
+Well, mail should stay more under the control of the user than news is.
+When you come back from a vacation, you expect to see all messages
+arrived during that time, not only the recent ones!
+
+Because of this, Gnus offers you the @kbd{E} key. This marks a message
+as expirable. No mail is ever deleted from disk, unless it is
+expirable. Every once in a while (by default, whenever you quit a group
+by hitting @kbd{q} in the Summary buffer), the expiry process is run,
+which goes through all expirable messages (of a group) and expires it if
+old enough. By default, messages older than seven days are ``old
+enough''. Seven days, that is, since it was marked as expirable.
+
+@quotation
+CCC Last sentence correct?
+@end quotation
+
+``But when I read a message, exit the group, then enter it again, the
+message is gone!''
+
+Right. By default, Gnus hides messages which have already been read.
+If you are the keyboard type, you can hit @kbd{C-u @key{RET}} or
+@kbd{C-u @key{SPC}} to enter the group or @kbd{C-u M-g} when in the
+group to look at the read messages. If you are the mousey type, you may
+wish to use the ``See old articles'' entry in the ``Group'' menu.
+
+@quotation
+CCC How does one code menu entries in TeXinfo?
+@end quotation
+
+
+@subsection Why auto-expire and total-expire?
+
+When reading mail, by default Gnus marks as read each message that you
+read. If you want to mark it as expirable, you have to hit @kbd{E}.
+Many people are subscribed to mailing lists and they configure Gnus to
+put mails from a mailing list into their own group. Most messages in
+such groups should be expirable, once read. But hitting @kbd{E} all the
+gets old real quick. Hence, auto-expire and total-expire were invented.
+
+
+@subsection Auto-expire vs.@ total-expire
+
+Auto-expire and total-expire both aim at the same goal: articles which
+are read should normally be expired, only if one does something special
+should these articles be saved on disk. But what happens when a message
+is being read by you, the user? Well, the message is marked as read
+(with the `R' mark). So, what can be done to make these messages
+expire? Well, two approaches come to mind: one idea is to change the
+mark that is attached to messages that you read, and the other idea is
+to make the `R' articles expirable. These are @emph{exactly} the things
+that are done in Gnus: auto-expire means to change the mark that is
+attached to a message that is being read, and total-expire means to
+change the meaning of the `R' mark to mean expirable.
+
+A more precise description of auto-expire might be the following: If an
+article is unmarked and then selected for reading,@footnote{Using
+@kbd{g}, or @kbd{@key{mouse-2}}, or by moving to it with @kbd{n} or
+@kbd{p}, or by one of the many other methods provided by Gnus.} it is
+marked with `E', as if the user had hit @kbd{E}.
+
+It is important to realize that auto-expire has @emph{no other}
+consequences. Selecting a message for reading which wasn't unmarked
+doesn't do anything special, and hitting @kbd{d} on a message also
+doesn't do anything special. (It therefore marks the message as read,
+not as expirable!)
+
+Now, forget about auto-expire, empty your mind and prepare to learn
+about total-expire. Like I said, total-expire changes what it means for
+an article to be marked as read.
+
+A more precise description of total-expire might be the following: When
+the expire process is run (for example, when you leave a group with
+@kbd{q}), all messages marked as read are considered to be expirable, as
+if they had been marked with `E'. Recall that there are several ways to
+mark a message as read: by reading it, by hitting @kbd{d} on it, and in
+a few other ways which I haven't mentioned so far. Recall that, in
+addition to the messages marked with `R', also those marked with `r' or
+`O' are considered to be marked as read.
+
+Can auto-expire and total-expire be used together? Well, in principle
+they can, but that doesn't make sense. Just using total-expire alone
+achieves the same effect.
+
+So, how do auto-expire and total-expire compare? Well, for once thing,
+hitting @kbd{d} on a message means it is expirable if total-expire is
+on (since it is marked as read and all messages marked as read are
+considered expirable when total-expire is on), but it is not expirable
+if auto-expire is on (since it is marked as read and only articles
+marked expirable (`E') are considered to be expirable). If you want to
+mark a message as expirable when total-expire is off, use @kbd{E}.
+
+One way of comparing auto-expire and total-expire is to compare the
+message marks that are available, and what they mean. Since auto-expire
+does not change the meaning of marks, its behavior is the same as in the
+default case. It's only important whether total-expire is on or off.
+Thus, there are only two cases: the default case and the total-expire
+case.
+
+@subsubsection Article marks with and without total-expire
+
+The following are the default article marks and behavior:
+
+@table @dfn
+@item unmarked
+All new messages are unmarked. This means you haven't seen them. They
+are always shown and won't be deleted.
+
+@item read
+Messages marked as read are not shown by default but kept on disk till
+hell freezes over. You can show them with @kbd{C-u M-g} from the
+summary buffer, or with @kbd{C-u @key{SPC}} or with the `Group' menu
+item `See old articles' from the group buffer.
+
+Depending on the setting of @var{gnus-fetch-old-headers}, a message
+marked as read might be shown if there is a followup or reply to it.
+
+@item dormant
+Dormant messages aren't shown by default but kept on disk till hell
+freezes over. You can show them with @kbd{/ D} from the summary buffer.
+If there is a reply or followup to a dormant message, the dormant
+message is also shown.
+
+@item ticked
+Ticked messages are always shown and kept on disk till hell freezes
+over.
+
+@item expirable
+Expirable messages will be deleted in due time. They are not shown by
+default, but you can make them appear with @kbd{C-u M-g} and so on,
+similar to the read ones.
+
+@end table
+
+Please note that the behavior for ticked messages is similar to the
+unread ones, and that the behavior of dormant messages is similar to the
+read ones. Especially the second fact will become important when we
+look at
+
+The behavior of the article marks with total-expire:
+
+@table @dfn
+@item unmarked
+Same as in the default case.
+
+@item expirable
+Same as in the default case.
+
+@item read
+Same as expirable.
+
+@item dormant
+Same as in the default case.
+
+@item ticked
+Same as in the default case.
+
+@end table
+
+As you can see, only the behavior of the read messages is different, and
+you can use the dormant mark if you want to achieve behavior similar to
+the behavior of read messages in the default case.
+
+
+@subsubsection Speed issues
+
+Total-expire may be slow when expiry happens. Why is that? Well, Gnus
+keeps an explicit list of all expirable messages (the ones marked `E'
+without taking total-expire into account), as well as a list of dormant
+messages, and a list of ticked messages. Normally, when expiration time
+comes, Gnus goes through all articles in the expire list and looks if
+they are old enough to be expired.
+
+However, for read messages the situation is different. Here, Gnus just
+keeps a list of ranges of article numbers to be able to distinguish read
+messages from unmarked ones. The assumption is that a message is to be
+considered marked as read if it falls in one of the ranges and isn't
+mentioned in any of the expirable, dormant or ticked lists.
+
+When total-expire is turned on, Gnus needs to go through all messages in
+the read range in order to look if it's in one of the lists. If the
+message is not in the ticked or dormant list, it is expirable and thus
+Gnus looks to see if it is old enough.
+
+Obviously, going through all the articles in the read ranges takes more
+time than going through just the list of expirable articles.
+
+Something can be done about the speed issue, though. Normally, the
+expiry process is started whenever you leave a group. I suggest that
+you disable this and instead run expiry just once per day, for example
+while you are going for lunch. This means that expiry still takes a
+long time, but you don't see it and thus it doesn't bother you.
+
+Here's how to do that: You disable the expire-on-group-exit thing with
+the following line in your @file{~/.gnus} file:
+@lisp
+(remove-hook 'gnus-summary-prepare-exit-hook
+ 'gnus-summary-expire-articles)
+@end lisp
+And before you leave for lunch, you hit @kbd{C-M-x}, or @kbd{M-x
+gnus-group-expire-all-groups @key{RET}}.
+
+
+@subsubsection Functionality
+
+Adaptive scoring doesn't work with auto-expire. (But normal scoring
+still works fine.) Adaptive scoring works fine with total-expire.
+
+
+@subsubsection A summary
+
+Well, it is difficult to sum up the whole discussion. I used to use
+total-expire but have switched to auto-expire a long time ago. I liked
+the fact that I could use one more kind of article mark. I also liked
+the fact that marking a message as read works the same in auto-expirable
+groups and in normal mail groups: you hit @kbd{E}. (With total-expire,
+you normally hit @kbd{d} but must remember to use @kbd{E} for those
+groups where total-expire is off.) And I liked that auto-expire is
+faster.
+
+On the other hand, adaptive scoring is surely a very useful feature (I'm
+just beginning to use it), so many people might prefer total-expire.
+
+And on a third hand, maybe the key binding issue isn't so important
+after all. You see, in mail groups the @kbd{d} key means `keep this
+message for archival purposes', whereas in many other modes (dired, CCC
+others?) it stands for `delete'. I propose to make it mean delete in
+mail groups, too, with the following line in
+@file{~/.gnus}:@footnote{See the chapter on key bindings; maybe you need
+a `require' statement.}
+@lisp
+(define-key gnus-summary-mode-map "d" 'gnus-summary-mark-as-expirable)
+@end lisp
+Marking messages as expirable (rather than read) in news groups does no
+harm, nor does it harm to do so in total-expirable mail groups. The old
+`keep this message' semantics can still be had by marking a message as
+dormant or by using @kbd{M r} (in non-total-expirable groups only).
+
+
+@c ------------------------------------------------------------
+@section Migrating old mail
+@c ------------------------------------------------------------
+
+Probably, you've been reading mail in pre-Gnus times, right? And surely
+you wish to carry this over to Gnus. Well, I haven't found a real good
+way to do it, but I can offer a few suggestions for doing it at least
+semi-automatically.
+
+One way of getting at your old mail is to type @kbd{G f}, and to then
+enter the name of your old mail file. This provides read-only access to
+your mails. For some people, this might be sufficient. (With @kbd{G
+f}, you have created an @code{nndoc} group.)
+
+Some people might want to have their mails available in their normal
+mail groups hierarchy. That's simple, just create an @code{nndoc} group
+for your mail file, then mark all messages in it with @kbd{M P a}, then
+copy all of them over to a normal mail group, with @kbd{B c}.
+
+This is good for people who wish to keep their old arrangement of
+folders, and who have a one-to-one correspondence between old mail files
+and new Gnus groups. But some people might wish to split up their mails
+differently. For them, it might be useful to set up
+@var{nnmail-split-methods} correctly and to use @kbd{B r} instead of
+@kbd{B c}. This goes through all process-marked messages and subjects
+them to the same splitting process that newly arriving messages go
+through. (Whee! What a run-on sentence!)
+
+
+@section TODO
+
+@table @bullet
+@item
+Say something about the cache. Though this belongs in the news reading
+tips, right? Hm.
+@end table
+
+
+@c Local Variables:
+@c TeX-master: "tutorials.texi"
+@c End:
Yank the message that's being replied to into the message buffer
(@code{message-yank-original}).
-@item C-c C-Y
-@kindex C-c C-Y
+@item C-c M-C-y
+@kindex C-c M-C-y
@findex message-yank-buffer
Prompt for a buffer name and yank the contents of that buffer into the
message buffer (@code{message-yank-buffer}).